mirror of
https://github.com/Sheldan/abstracto.git
synced 2026-06-13 22:26:39 +00:00
[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:
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -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.");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -6,6 +6,7 @@ import dev.sheldan.abstracto.assignableroles.model.database.AssignableRolePlaceP
|
||||
import dev.sheldan.abstracto.core.models.cache.CachedEmote;
|
||||
import dev.sheldan.abstracto.core.models.database.AEmote;
|
||||
import dev.sheldan.abstracto.core.models.database.ARole;
|
||||
import net.dv8tion.jda.api.entities.MessageReaction;
|
||||
|
||||
/**
|
||||
* Management service for the table of {@link AssignableRole assignableRoles}
|
||||
@@ -64,4 +65,5 @@ public interface AssignableRoleManagementService {
|
||||
* @return An instance of {@link AssignableRole role} which was in the place and identified by the emote
|
||||
*/
|
||||
AssignableRole getRoleForReactionEmote(CachedEmote cachedEmote, AssignableRolePlace assignableRolePlace);
|
||||
AssignableRole getRoleForReactionEmote(MessageReaction.ReactionEmote cachedEmote, AssignableRolePlace assignableRolePlace);
|
||||
}
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
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.AsyncMessageReceivedListener;
|
||||
import dev.sheldan.abstracto.core.listener.sync.jda.MessageReceivedListener;
|
||||
import dev.sheldan.abstracto.core.models.cache.CachedMessage;
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.core.models.listener.MessageReceivedModel;
|
||||
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
|
||||
import dev.sheldan.abstracto.experience.config.ExperienceFeatureDefinition;
|
||||
import dev.sheldan.abstracto.experience.service.AUserExperienceService;
|
||||
@@ -27,9 +28,10 @@ public class ExperienceTrackerListener implements AsyncMessageReceivedListener {
|
||||
private UserInServerManagementService userInServerManagementService;
|
||||
|
||||
@Override
|
||||
public void execute(CachedMessage message) {
|
||||
AUserInAServer cause = userInServerManagementService.loadOrCreateUser(message.getServerId(), message.getAuthor().getAuthorId());
|
||||
public DefaultListenerResult execute(MessageReceivedModel model) {
|
||||
AUserInAServer cause = userInServerManagementService.loadOrCreateUser(model.getServerId(), model.getMessage().getAuthor().getIdLong());
|
||||
userExperienceService.addExperience(cause);
|
||||
return DefaultListenerResult.PROCESSED;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
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.AsyncJoinListener;
|
||||
import dev.sheldan.abstracto.core.listener.sync.jda.JoinListener;
|
||||
import dev.sheldan.abstracto.core.models.ServerUser;
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.core.models.listener.MemberJoinModel;
|
||||
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
|
||||
import dev.sheldan.abstracto.experience.config.ExperienceFeatureDefinition;
|
||||
import dev.sheldan.abstracto.experience.model.database.AUserExperience;
|
||||
@@ -33,18 +34,20 @@ public class JoiningUserRoleListener implements AsyncJoinListener {
|
||||
private UserInServerManagementService userInServerManagementService;
|
||||
|
||||
@Override
|
||||
public void execute(ServerUser serverUser) {
|
||||
AUserInAServer userInAServer = userInServerManagementService.loadOrCreateUser(serverUser.getServerId(), serverUser.getUserId());
|
||||
public DefaultListenerResult execute(MemberJoinModel model) {
|
||||
AUserInAServer userInAServer = userInServerManagementService.loadOrCreateUser(model.getServerId(), model.getJoiningUser().getUserId());
|
||||
AUserExperience userExperience = userExperienceManagementService.findUserInServer(userInAServer);
|
||||
Long userInServerId = userInAServer.getUserInServerId();
|
||||
if(userExperience != null) {
|
||||
log.info("User {} joined {} with previous experience. Setting up experience role again (if necessary).", serverUser.getUserId(), serverUser.getServerId());
|
||||
log.info("User {} joined {} with previous experience. Setting up experience role again (if necessary).", model.getJoiningUser().getUserId(), model.getServerId());
|
||||
userExperienceService.syncForSingleUser(userExperience).thenAccept(result ->
|
||||
log.info("Finished re-assigning experience for re-joining user {} in server {}.", userInServerId, serverUser.getServerId())
|
||||
log.info("Finished re-assigning experience for re-joining user {} in server {}.", userInServerId, model.getServerId())
|
||||
);
|
||||
} else {
|
||||
log.info("Joined user {} in server {} does not have any previous experience. Not setting up anything.", serverUser.getUserId(), serverUser.getServerId());
|
||||
log.info("Joined user {} in server {} does not have any previous experience. Not setting up anything.", model.getJoiningUser().getUserId(), model.getServerId());
|
||||
}
|
||||
|
||||
return DefaultListenerResult.PROCESSED;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -93,7 +93,7 @@ public class ExperienceRoleManagementServiceBean implements ExperienceRoleManage
|
||||
.role(role)
|
||||
.build();
|
||||
log.trace("Role did not exist. Creating new.");
|
||||
experienceRole = experienceRoleRepository.save(experienceRole);
|
||||
return experienceRoleRepository.save(experienceRole);
|
||||
}
|
||||
return experienceRole;
|
||||
}
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
package dev.sheldan.abstracto.experience.listener;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.cache.CachedAuthor;
|
||||
import dev.sheldan.abstracto.core.models.cache.CachedMessage;
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import dev.sheldan.abstracto.core.models.database.AUser;
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.core.models.listener.MessageReceivedModel;
|
||||
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
|
||||
import dev.sheldan.abstracto.experience.service.AUserExperienceService;
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
import net.dv8tion.jda.api.entities.User;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.InjectMocks;
|
||||
@@ -28,16 +27,25 @@ public class ExperienceTrackerListenerTest {
|
||||
@Mock
|
||||
private UserInServerManagementService userInServerManagementService;
|
||||
|
||||
@Mock
|
||||
private MessageReceivedModel model;
|
||||
|
||||
@Mock
|
||||
private User user;
|
||||
|
||||
private static final Long SERVER_ID = 4L;
|
||||
private static final Long USER_ID = 5L;
|
||||
|
||||
@Test
|
||||
public void testExperienceTracking() {
|
||||
AServer server = Mockito.mock(AServer.class);
|
||||
AUser user = Mockito.mock(AUser.class);
|
||||
AUserInAServer userInAServer = Mockito.mock(AUserInAServer.class);
|
||||
CachedMessage mockedMessage = Mockito.mock(CachedMessage.class);
|
||||
CachedAuthor cachedAuthor = Mockito.mock(CachedAuthor.class);
|
||||
when(mockedMessage.getAuthor()).thenReturn(cachedAuthor);
|
||||
when(userInServerManagementService.loadOrCreateUser(server.getId(), user.getId())).thenReturn(userInAServer);
|
||||
testUnit.execute(mockedMessage);
|
||||
Message mockedMessage = Mockito.mock(Message.class);
|
||||
when(userInServerManagementService.loadOrCreateUser(SERVER_ID, USER_ID)).thenReturn(userInAServer);
|
||||
when(model.getMessage()).thenReturn(mockedMessage);
|
||||
when(model.getServerId()).thenReturn(SERVER_ID);
|
||||
when(mockedMessage.getAuthor()).thenReturn(user);
|
||||
when(user.getIdLong()).thenReturn(USER_ID);
|
||||
testUnit.execute(model);
|
||||
verify(userExperienceService, times(1)).addExperience(userInAServer);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package dev.sheldan.abstracto.experience.listener;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.ServerUser;
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.core.models.listener.MemberJoinModel;
|
||||
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
|
||||
import dev.sheldan.abstracto.experience.model.database.AUserExperience;
|
||||
import dev.sheldan.abstracto.experience.service.AUserExperienceService;
|
||||
@@ -39,6 +40,9 @@ public class JoiningUserRoleListenerTest {
|
||||
@Mock
|
||||
private AUserInAServer aUserInAServer;
|
||||
|
||||
@Mock
|
||||
private MemberJoinModel model;
|
||||
|
||||
private static final Long SERVER_ID = 1L;
|
||||
private static final Long USER_ID = 2L;
|
||||
|
||||
@@ -46,6 +50,7 @@ public class JoiningUserRoleListenerTest {
|
||||
public void setup() {
|
||||
when(serverUser.getServerId()).thenReturn(SERVER_ID);
|
||||
when(serverUser.getUserId()).thenReturn(USER_ID);
|
||||
when(model.getJoiningUser()).thenReturn(serverUser);
|
||||
when(userInServerManagementService.loadOrCreateUser(SERVER_ID, USER_ID)).thenReturn(aUserInAServer);
|
||||
}
|
||||
|
||||
@@ -54,13 +59,13 @@ public class JoiningUserRoleListenerTest {
|
||||
AUserExperience experience = Mockito.mock(AUserExperience.class);
|
||||
when(userExperienceManagementService.findUserInServer(aUserInAServer)).thenReturn(experience);
|
||||
when(userExperienceService.syncForSingleUser(experience)).thenReturn(CompletableFuture.completedFuture(null));
|
||||
testUnit.execute(serverUser);
|
||||
testUnit.execute(model);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUserWithOutExperienceRejoining() {
|
||||
when(userExperienceManagementService.findUserInServer(aUserInAServer)).thenReturn(null);
|
||||
testUnit.execute(serverUser);
|
||||
testUnit.execute(model);
|
||||
verify(userExperienceService, times(0)).syncForSingleUser(any());
|
||||
}
|
||||
|
||||
|
||||
@@ -2,13 +2,13 @@ package dev.sheldan.abstracto.linkembed.listener;
|
||||
|
||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
import dev.sheldan.abstracto.core.config.ListenerPriority;
|
||||
import dev.sheldan.abstracto.core.execution.result.ExecutionResult;
|
||||
import dev.sheldan.abstracto.core.execution.result.MessageReceivedListenerResult;
|
||||
import dev.sheldan.abstracto.core.listener.ConsumableListenerResult;
|
||||
import dev.sheldan.abstracto.core.listener.sync.jda.MessageReceivedListener;
|
||||
import dev.sheldan.abstracto.core.metric.service.CounterMetric;
|
||||
import dev.sheldan.abstracto.core.metric.service.MetricService;
|
||||
import dev.sheldan.abstracto.core.metric.service.MetricTag;
|
||||
import dev.sheldan.abstracto.core.models.cache.CachedMessage;
|
||||
import dev.sheldan.abstracto.core.models.listener.MessageReceivedModel;
|
||||
import dev.sheldan.abstracto.core.service.MessageCache;
|
||||
import dev.sheldan.abstracto.core.service.MessageService;
|
||||
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
|
||||
@@ -59,7 +59,8 @@ public class MessageEmbedListener implements MessageReceivedListener {
|
||||
.build();
|
||||
|
||||
@Override
|
||||
public MessageReceivedListenerResult execute(Message message) {
|
||||
public ConsumableListenerResult execute(MessageReceivedModel model) {
|
||||
Message message = model.getMessage();
|
||||
String messageRaw = message.getContentRaw();
|
||||
List<MessageEmbedLink> links = messageEmbedService.getLinksInMessage(messageRaw);
|
||||
if(!links.isEmpty()) {
|
||||
@@ -82,12 +83,12 @@ public class MessageEmbedListener implements MessageReceivedListener {
|
||||
}
|
||||
if(StringUtils.isBlank(messageRaw) && !links.isEmpty()) {
|
||||
messageService.deleteMessage(message);
|
||||
return MessageReceivedListenerResult.DELETED;
|
||||
return ConsumableListenerResult.DELETED;
|
||||
}
|
||||
if(!links.isEmpty()) {
|
||||
return MessageReceivedListenerResult.PROCESSED;
|
||||
return ConsumableListenerResult.PROCESSED;
|
||||
}
|
||||
return MessageReceivedListenerResult.IGNORED;
|
||||
return ConsumableListenerResult.IGNORED;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@@ -104,8 +105,8 @@ public class MessageEmbedListener implements MessageReceivedListener {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldConsume(Event event, ExecutionResult result) {
|
||||
return result.equals(MessageReceivedListenerResult.DELETED);
|
||||
public boolean shouldConsume(Event event, ConsumableListenerResult result) {
|
||||
return result.equals(ConsumableListenerResult.DELETED);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
package dev.sheldan.abstracto.linkembed.listener;
|
||||
|
||||
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.metric.service.CounterMetric;
|
||||
import dev.sheldan.abstracto.core.metric.service.MetricService;
|
||||
import dev.sheldan.abstracto.core.metric.service.MetricTag;
|
||||
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.database.AEmote;
|
||||
import dev.sheldan.abstracto.core.models.listener.ReactionAddedModel;
|
||||
import dev.sheldan.abstracto.core.service.BotService;
|
||||
import dev.sheldan.abstracto.core.service.EmoteService;
|
||||
import dev.sheldan.abstracto.core.service.MessageService;
|
||||
@@ -59,21 +58,22 @@ public class MessageEmbedRemovalReactionListener implements AsyncReactionAddedLi
|
||||
.tagList(Arrays.asList(MetricTag.getTag(MESSAGE_EMBED_ACTION, "removed.source")))
|
||||
.build();
|
||||
|
||||
|
||||
@Override
|
||||
public void executeReactionAdded(CachedMessage message, CachedReactions cachedReaction, ServerUser serverUser) {
|
||||
Long guildId = message.getServerId();
|
||||
AEmote aEmote = emoteService.getEmoteOrDefaultEmote(REMOVAL_EMOTE, guildId);
|
||||
if(emoteService.compareCachedEmoteWithAEmote(cachedReaction.getEmote(), aEmote)) {
|
||||
Optional<EmbeddedMessage> embeddedMessageOptional = messageEmbedPostManagementService.findEmbeddedPostByMessageId(message.getMessageId());
|
||||
public DefaultListenerResult execute(ReactionAddedModel model) {
|
||||
Long serverId = model.getServerId();
|
||||
AEmote aEmote = emoteService.getEmoteOrDefaultEmote(REMOVAL_EMOTE, serverId);
|
||||
if(emoteService.isReactionEmoteAEmote(model.getReaction().getReactionEmote(), aEmote)) {
|
||||
Long messageId = model.getMessage().getMessageId();
|
||||
Optional<EmbeddedMessage> embeddedMessageOptional = messageEmbedPostManagementService.findEmbeddedPostByMessageId(messageId);
|
||||
if(embeddedMessageOptional.isPresent()) {
|
||||
Long channelId = model.getMessage().getChannelId();
|
||||
EmbeddedMessage embeddedMessage = embeddedMessageOptional.get();
|
||||
boolean embeddedUserRemoves = embeddedMessage.getEmbeddedUser().getUserReference().getId().equals(serverUser.getUserId());
|
||||
boolean embeddingUserRemoves = embeddedMessage.getEmbeddingUser().getUserReference().getId().equals(serverUser.getUserId());
|
||||
boolean embeddedUserRemoves = embeddedMessage.getEmbeddedUser().getUserReference().getId().equals(model.getUserReacting().getUserId());
|
||||
boolean embeddingUserRemoves = embeddedMessage.getEmbeddingUser().getUserReference().getId().equals(model.getUserReacting().getUserId());
|
||||
if(embeddedUserRemoves || embeddingUserRemoves) {
|
||||
log.info("Removing embed in message {} in channel {} in server {} because of a user reaction.", message.getMessageId(), message.getChannelId(), message.getServerId());
|
||||
messageService.deleteMessageInChannelInServer(message.getServerId(), message.getChannelId(), message.getMessageId()).thenAccept(aVoid -> {
|
||||
Optional<EmbeddedMessage> innerOptional = messageEmbedPostManagementService.findEmbeddedPostByMessageId(message.getMessageId());
|
||||
log.info("Removing embed in message {} in channel {} in server {} because of a user reaction.", messageId, channelId, serverId);
|
||||
messageService.deleteMessageInChannelInServer(serverId, channelId, messageId).thenAccept(aVoid -> {
|
||||
Optional<EmbeddedMessage> innerOptional = messageEmbedPostManagementService.findEmbeddedPostByMessageId(messageId);
|
||||
innerOptional.ifPresent(value -> messageEmbedPostManagementService.deleteEmbeddedMessage(value));
|
||||
if(embeddedUserRemoves) {
|
||||
metricService.incrementCounter(MESSAGE_EMBED_REMOVED_SOURCE);
|
||||
@@ -83,13 +83,19 @@ public class MessageEmbedRemovalReactionListener implements AsyncReactionAddedLi
|
||||
});
|
||||
} else {
|
||||
log.trace("Somebody besides the original author and the user embedding added the removal reaction to the message {} in channel {} in server {}.",
|
||||
message.getMessageId(), message.getChannelId(), message.getServerId());
|
||||
messageId, channelId, serverId);
|
||||
return DefaultListenerResult.IGNORED;
|
||||
}
|
||||
|
||||
} else {
|
||||
log.trace("Removal emote was placed on a message which was not recognized as an embedded message.");
|
||||
return DefaultListenerResult.IGNORED;
|
||||
}
|
||||
return DefaultListenerResult.PROCESSED;
|
||||
} else {
|
||||
return DefaultListenerResult.IGNORED;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -3,6 +3,7 @@ package dev.sheldan.abstracto.linkembed.listener;
|
||||
import dev.sheldan.abstracto.core.metric.service.MetricService;
|
||||
import dev.sheldan.abstracto.core.models.cache.CachedMessage;
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.core.models.listener.MessageReceivedModel;
|
||||
import dev.sheldan.abstracto.core.service.MessageCache;
|
||||
import dev.sheldan.abstracto.core.service.MessageService;
|
||||
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
|
||||
@@ -57,6 +58,9 @@ public class MessageEmbedListenerTest {
|
||||
@Mock
|
||||
private TextChannel textChannel;
|
||||
|
||||
@Mock
|
||||
private MessageReceivedModel model;
|
||||
|
||||
@Mock
|
||||
private Guild guild;
|
||||
|
||||
@@ -80,7 +84,8 @@ public class MessageEmbedListenerTest {
|
||||
when(message.getContentRaw()).thenReturn(text);
|
||||
List<MessageEmbedLink> foundMessageLinks = new ArrayList<>();
|
||||
when(messageEmbedService.getLinksInMessage(text)).thenReturn(foundMessageLinks);
|
||||
testUnit.execute(message);
|
||||
when(model.getMessage()).thenReturn(message);
|
||||
testUnit.execute(model);
|
||||
verify(messageService, times(0)).deleteMessage(message);
|
||||
}
|
||||
|
||||
@@ -116,7 +121,8 @@ public class MessageEmbedListenerTest {
|
||||
when(message.getMember()).thenReturn(author);
|
||||
when(userInServerManagementService.loadOrCreateUser(author)).thenReturn(userInAServer);
|
||||
when(messageEmbedService.getLinksInMessage(text)).thenReturn(foundMessageLinks);
|
||||
testUnit.execute(message);
|
||||
when(model.getMessage()).thenReturn(message);
|
||||
testUnit.execute(model);
|
||||
verify(messageService, times(0)).deleteMessage(message);
|
||||
verify(self, times(0)).embedSingleLink(eq(message), anyLong(), any(CachedMessage.class));
|
||||
verify(messageCache, times(0)).getMessageFromCache(anyLong(), anyLong(), anyLong());
|
||||
@@ -148,7 +154,8 @@ public class MessageEmbedListenerTest {
|
||||
CachedMessage cachedMessage = Mockito.mock(CachedMessage.class);
|
||||
when(messageCache.getMessageFromCache(FIRST_SERVER_ID, FIRST_CHANNEL_ID, FIRST_MESSAGE_ID)).thenReturn(CompletableFuture.completedFuture(cachedMessage));
|
||||
when(messageEmbedService.getLinksInMessage(completeMessage)).thenReturn(foundMessageLinks);
|
||||
testUnit.execute(message);
|
||||
when(model.getMessage()).thenReturn(message);
|
||||
testUnit.execute(model);
|
||||
verify(messageService, times(0)).deleteMessage(message);
|
||||
verify(self, times(1)).embedSingleLink(message, USER_IN_SERVER_ID, cachedMessage);
|
||||
}
|
||||
@@ -179,7 +186,8 @@ public class MessageEmbedListenerTest {
|
||||
when(messageCache.getMessageFromCache(FIRST_SERVER_ID, FIRST_CHANNEL_ID, FIRST_MESSAGE_ID)).thenReturn(CompletableFuture.completedFuture(cachedMessage));
|
||||
when(messageCache.getMessageFromCache(FIRST_SERVER_ID, FIRST_CHANNEL_ID, SECOND_MESSAGE_ID)).thenReturn(CompletableFuture.completedFuture(secondCachedMessage));
|
||||
when(messageEmbedService.getLinksInMessage(text)).thenReturn(foundMessageLinks);
|
||||
testUnit.execute(message);
|
||||
when(model.getMessage()).thenReturn(message);
|
||||
testUnit.execute(model);
|
||||
verify(messageService, times(1)).deleteMessage(message);
|
||||
verify(self, times(1)).embedSingleLink(message, USER_IN_SERVER_ID, cachedMessage);
|
||||
verify(self, times(1)).embedSingleLink(message, USER_IN_SERVER_ID, secondCachedMessage);
|
||||
@@ -210,7 +218,8 @@ public class MessageEmbedListenerTest {
|
||||
CachedMessage cachedMessage = Mockito.mock(CachedMessage.class);
|
||||
when(messageCache.getMessageFromCache(FIRST_SERVER_ID, FIRST_CHANNEL_ID, FIRST_MESSAGE_ID)).thenReturn(CompletableFuture.completedFuture(cachedMessage));
|
||||
when(messageEmbedService.getLinksInMessage(text)).thenReturn(foundMessageLinks);
|
||||
testUnit.execute(message);
|
||||
when(model.getMessage()).thenReturn(message);
|
||||
testUnit.execute(model);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -2,16 +2,16 @@ package dev.sheldan.abstracto.linkembed.listener;
|
||||
|
||||
import dev.sheldan.abstracto.core.metric.service.MetricService;
|
||||
import dev.sheldan.abstracto.core.models.ServerUser;
|
||||
import dev.sheldan.abstracto.core.models.cache.CachedEmote;
|
||||
import dev.sheldan.abstracto.core.models.cache.CachedMessage;
|
||||
import dev.sheldan.abstracto.core.models.cache.CachedReactions;
|
||||
import dev.sheldan.abstracto.core.models.database.AEmote;
|
||||
import dev.sheldan.abstracto.core.models.database.AUser;
|
||||
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.MessageService;
|
||||
import dev.sheldan.abstracto.linkembed.model.database.EmbeddedMessage;
|
||||
import dev.sheldan.abstracto.linkembed.service.management.MessageEmbedPostManagementService;
|
||||
import net.dv8tion.jda.api.entities.MessageReaction;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.InjectMocks;
|
||||
@@ -43,10 +43,10 @@ public class MessageEmbedRemovalReactionListenerTest {
|
||||
private MetricService metricService;
|
||||
|
||||
@Mock
|
||||
private CachedReactions messageReaction;
|
||||
private MessageReaction messageReaction;
|
||||
|
||||
@Mock
|
||||
private CachedEmote reactionEmote;
|
||||
private MessageReaction.ReactionEmote reactionEmote;
|
||||
|
||||
@Mock
|
||||
private AUserInAServer embeddingUser;
|
||||
@@ -63,6 +63,9 @@ public class MessageEmbedRemovalReactionListenerTest {
|
||||
@Mock
|
||||
private ServerUser reactingUser;
|
||||
|
||||
@Mock
|
||||
private ReactionAddedModel model;
|
||||
|
||||
private static final Long SERVER_ID = 4L;
|
||||
private static final Long CHANNEL_ID = 5L;
|
||||
private static final Long MESSAGE_ID = 6L;
|
||||
@@ -87,7 +90,7 @@ public class MessageEmbedRemovalReactionListenerTest {
|
||||
when(embeddingAUser.getId()).thenReturn(USER_ID);
|
||||
when(embeddedAUser.getId()).thenReturn(USER_ID + 1);
|
||||
when(reactingUser.getUserId()).thenReturn(USER_ID + 2);
|
||||
executeDeletionTest(embeddingUser, embeddedUser, reactingUser, 0);
|
||||
executeDeletionTest(embeddingUser, embeddedUser, 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -97,7 +100,7 @@ public class MessageEmbedRemovalReactionListenerTest {
|
||||
when(embeddingUser.getUserReference()).thenReturn(embeddingAUser);
|
||||
when(embeddingAUser.getId()).thenReturn(USER_ID + 3);
|
||||
when(reactingUser.getUserId()).thenReturn(USER_ID + 1);
|
||||
executeDeletionTest(embeddingUser, embeddedUser, reactingUser, 1);
|
||||
executeDeletionTest(embeddingUser, embeddedUser, 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -107,25 +110,28 @@ public class MessageEmbedRemovalReactionListenerTest {
|
||||
when(embeddingAUser.getId()).thenReturn(USER_ID);
|
||||
when(embeddedAUser.getId()).thenReturn(USER_ID + 1);
|
||||
when(reactingUser.getUserId()).thenReturn(USER_ID);
|
||||
executeDeletionTest(embeddingUser, embeddedUser, reactingUser, 1);
|
||||
executeDeletionTest(embeddingUser, embeddedUser, 1);
|
||||
}
|
||||
|
||||
private void executeDeletionTest(AUserInAServer embeddingUser, AUserInAServer embeddedUser, ServerUser userAddingReaction, int wantedDeletions) {
|
||||
private void executeDeletionTest(AUserInAServer embeddingUser, AUserInAServer embeddedUser, int wantedDeletions) {
|
||||
CachedMessage cachedMessage = Mockito.mock(CachedMessage.class);
|
||||
when(cachedMessage.getServerId()).thenReturn(SERVER_ID);
|
||||
when(cachedMessage.getChannelId()).thenReturn(CHANNEL_ID);
|
||||
when(cachedMessage.getMessageId()).thenReturn(MESSAGE_ID);
|
||||
AEmote reactedEmote = Mockito.mock(AEmote.class);
|
||||
when(emoteService.getEmoteOrDefaultEmote(MessageEmbedRemovalReactionListener.REMOVAL_EMOTE, SERVER_ID)).thenReturn(reactedEmote);
|
||||
when(messageReaction.getEmote()).thenReturn(reactionEmote);
|
||||
when(emoteService.compareCachedEmoteWithAEmote(reactionEmote, reactedEmote)).thenReturn(true);
|
||||
when(messageReaction.getReactionEmote()).thenReturn(reactionEmote);
|
||||
when(emoteService.isReactionEmoteAEmote(reactionEmote, reactedEmote)).thenReturn(true);
|
||||
EmbeddedMessage message = Mockito.mock(EmbeddedMessage.class);
|
||||
when(message.getEmbeddingUser()).thenReturn(embeddingUser);
|
||||
when(message.getEmbeddedUser()).thenReturn(embeddedUser);
|
||||
when(messageEmbedPostManagementService.findEmbeddedPostByMessageId(MESSAGE_ID)).thenReturn(Optional.of(message));
|
||||
when(messageService.deleteMessageInChannelInServer(SERVER_ID, CHANNEL_ID, MESSAGE_ID)).thenReturn(CompletableFuture.completedFuture(null));
|
||||
when(messageEmbedPostManagementService.findEmbeddedPostByMessageId(MESSAGE_ID)).thenReturn(Optional.of(message));
|
||||
testUnit.executeReactionAdded(cachedMessage, messageReaction, userAddingReaction);
|
||||
when(model.getMessage()).thenReturn(cachedMessage);
|
||||
when(model.getReaction()).thenReturn(messageReaction);
|
||||
when(model.getServerId()).thenReturn(SERVER_ID);
|
||||
when(model.getUserReacting()).thenReturn(reactingUser);
|
||||
testUnit.execute(model);
|
||||
verify(messageService, times(wantedDeletions)).deleteMessageInChannelInServer(SERVER_ID, CHANNEL_ID, MESSAGE_ID);
|
||||
if(wantedDeletions > 0) {
|
||||
verify(messageEmbedPostManagementService, times(1)).deleteEmbeddedMessage(message);
|
||||
@@ -134,14 +140,15 @@ public class MessageEmbedRemovalReactionListenerTest {
|
||||
|
||||
private void executeRemovalEmoteAddedTest(boolean wasCorrectEmote) {
|
||||
CachedMessage cachedMessage = Mockito.mock(CachedMessage.class);
|
||||
when(cachedMessage.getServerId()).thenReturn(SERVER_ID);
|
||||
when(cachedMessage.getMessageId()).thenReturn(MESSAGE_ID);
|
||||
ServerUser serverUser = Mockito.mock(ServerUser.class);
|
||||
AEmote reactedEmote = Mockito.mock(AEmote.class);
|
||||
when(emoteService.getEmoteOrDefaultEmote(MessageEmbedRemovalReactionListener.REMOVAL_EMOTE, SERVER_ID)).thenReturn(reactedEmote);
|
||||
when(messageReaction.getEmote()).thenReturn(reactionEmote);
|
||||
when(emoteService.compareCachedEmoteWithAEmote(reactionEmote, reactedEmote)).thenReturn(wasCorrectEmote);
|
||||
testUnit.executeReactionAdded(cachedMessage, messageReaction, serverUser);
|
||||
when(messageReaction.getReactionEmote()).thenReturn(reactionEmote);
|
||||
when(emoteService.isReactionEmoteAEmote(reactionEmote, reactedEmote)).thenReturn(wasCorrectEmote);
|
||||
when(model.getMessage()).thenReturn(cachedMessage);
|
||||
when(model.getReaction()).thenReturn(messageReaction);
|
||||
when(model.getServerId()).thenReturn(SERVER_ID);
|
||||
testUnit.execute(model);
|
||||
verify(messageService, times(0)).deleteMessageInChannelInServer(anyLong(), anyLong(), anyLong());
|
||||
}
|
||||
|
||||
|
||||
@@ -2,12 +2,13 @@ package dev.sheldan.abstracto.moderation.listener;
|
||||
|
||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
import dev.sheldan.abstracto.core.config.ListenerPriority;
|
||||
import dev.sheldan.abstracto.core.execution.result.MessageReceivedListenerResult;
|
||||
import dev.sheldan.abstracto.core.listener.ConsumableListenerResult;
|
||||
import dev.sheldan.abstracto.core.listener.sync.jda.MessageReceivedListener;
|
||||
import dev.sheldan.abstracto.core.metric.service.CounterMetric;
|
||||
import dev.sheldan.abstracto.core.metric.service.MetricService;
|
||||
import dev.sheldan.abstracto.core.metric.service.MetricTag;
|
||||
import dev.sheldan.abstracto.core.models.ServerUser;
|
||||
import dev.sheldan.abstracto.core.models.listener.MessageReceivedModel;
|
||||
import dev.sheldan.abstracto.core.service.FeatureModeService;
|
||||
import dev.sheldan.abstracto.core.service.MessageService;
|
||||
import dev.sheldan.abstracto.core.service.PostTargetService;
|
||||
@@ -69,7 +70,8 @@ public class InviteLinkFilterListener implements MessageReceivedListener {
|
||||
public static final String INVITE_LINK_DELETED_NOTIFICATION_EMBED_TEMPLATE_KEY = "invite_link_deleted_notification";
|
||||
|
||||
@Override
|
||||
public MessageReceivedListenerResult execute(Message message) {
|
||||
public ConsumableListenerResult execute(MessageReceivedModel model) {
|
||||
Message message = model.getMessage();
|
||||
Long serverId = message.getGuild().getIdLong();
|
||||
Matcher matcher = Message.INVITE_PATTERN.matcher(message.getContentRaw());
|
||||
ServerUser author = ServerUser.builder().userId(message.getAuthor().getIdLong()).serverId(message.getGuild().getIdLong()).build();
|
||||
@@ -95,9 +97,9 @@ public class InviteLinkFilterListener implements MessageReceivedListener {
|
||||
if(sendNotification) {
|
||||
sendDeletionNotification(codesToTrack, message);
|
||||
}
|
||||
return MessageReceivedListenerResult.DELETED;
|
||||
return ConsumableListenerResult.DELETED;
|
||||
} else {
|
||||
return MessageReceivedListenerResult.PROCESSED;
|
||||
return ConsumableListenerResult.PROCESSED;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,19 +1,18 @@
|
||||
package dev.sheldan.abstracto.moderation.listener;
|
||||
|
||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
import dev.sheldan.abstracto.core.listener.DefaultListenerResult;
|
||||
import dev.sheldan.abstracto.core.listener.async.jda.AsyncJoinListener;
|
||||
import dev.sheldan.abstracto.core.models.ServerUser;
|
||||
import dev.sheldan.abstracto.core.models.listener.MemberJoinModel;
|
||||
import dev.sheldan.abstracto.core.service.MemberService;
|
||||
import dev.sheldan.abstracto.core.service.PostTargetService;
|
||||
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
||||
import dev.sheldan.abstracto.moderation.config.feature.ModerationFeatureDefinition;
|
||||
import dev.sheldan.abstracto.moderation.config.posttarget.LoggingPostTarget;
|
||||
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
import net.dv8tion.jda.api.entities.User;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
@@ -42,20 +41,14 @@ public class JoinLogger implements AsyncJoinListener {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(ServerUser serverUser) {
|
||||
log.info("User {} joined server {}.", serverUser.getUserId(), serverUser.getServerId());
|
||||
memberService.getMemberInServerAsync(serverUser.getServerId(), serverUser.getUserId()).thenAccept(member ->
|
||||
self.sendJoinLog(serverUser, member)
|
||||
);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void sendJoinLog(ServerUser serverUser, Member member) {
|
||||
HashMap<String, Object> parameters = getUserParameter(member.getUser());
|
||||
public DefaultListenerResult execute(MemberJoinModel serverUser) {
|
||||
HashMap<String, Object> parameters = getUserParameter(serverUser.getMember().getUser());
|
||||
String text = templateService.renderTemplateWithMap(USER_JOIN_TEMPLATE, parameters, serverUser.getServerId());
|
||||
postTargetService.sendTextInPostTarget(text, LoggingPostTarget.JOIN_LOG, serverUser.getServerId());
|
||||
return DefaultListenerResult.PROCESSED;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public FeatureDefinition getFeature() {
|
||||
return ModerationFeatureDefinition.LOGGING;
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
package dev.sheldan.abstracto.moderation.listener;
|
||||
|
||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
import dev.sheldan.abstracto.core.listener.DefaultListenerResult;
|
||||
import dev.sheldan.abstracto.core.listener.async.jda.AsyncJoinListener;
|
||||
import dev.sheldan.abstracto.core.models.ServerUser;
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.core.models.listener.MemberJoinModel;
|
||||
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
|
||||
import dev.sheldan.abstracto.moderation.config.feature.ModerationFeatureDefinition;
|
||||
import dev.sheldan.abstracto.moderation.service.MuteService;
|
||||
@@ -26,12 +27,13 @@ public class JoinMuteListener implements AsyncJoinListener {
|
||||
private UserInServerManagementService userInServerManagementService;
|
||||
|
||||
@Override
|
||||
public void execute(ServerUser serverUser) {
|
||||
AUserInAServer aUserInAServer = userInServerManagementService.loadOrCreateUser(serverUser.getServerId(), serverUser.getUserId());
|
||||
public DefaultListenerResult execute(MemberJoinModel model) {
|
||||
AUserInAServer aUserInAServer = userInServerManagementService.loadOrCreateUser(model.getServerId(), model.getJoiningUser().getUserId());
|
||||
if(muteManagementService.hasActiveMute(aUserInAServer)) {
|
||||
log.info("Re-muting user {} which joined the server {}, because the mute has not ended yet.", serverUser.getUserId(), serverUser.getServerId());
|
||||
log.info("Re-muting user {} which joined the server {}, because the mute has not ended yet.", model.getJoiningUser().getUserId(), model.getServerId());
|
||||
muteService.applyMuteRole(aUserInAServer);
|
||||
}
|
||||
return DefaultListenerResult.PROCESSED;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,20 +1,19 @@
|
||||
package dev.sheldan.abstracto.moderation.listener;
|
||||
|
||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
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.service.MemberService;
|
||||
import dev.sheldan.abstracto.core.service.PostTargetService;
|
||||
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
||||
import dev.sheldan.abstracto.moderation.config.feature.ModerationFeatureDefinition;
|
||||
import dev.sheldan.abstracto.moderation.config.posttarget.LoggingPostTarget;
|
||||
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
import net.dv8tion.jda.api.entities.User;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.HashMap;
|
||||
@@ -45,23 +44,15 @@ public class LeaveLogger implements AsyncLeaveListener {
|
||||
return parameters;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(ServerUser serverUser) {
|
||||
log.info("User {} left server {}.", serverUser.getUserId(), serverUser.getServerId());
|
||||
memberService.getMemberInServerAsync(serverUser.getServerId(), serverUser.getUserId()).thenAccept(member ->
|
||||
self.executeJoinLogging(serverUser, member)
|
||||
);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void executeJoinLogging(ServerUser serverUser, Member member) {
|
||||
String text = templateService.renderTemplateWithMap(USER_LEAVE_TEMPLATE, getUserParameter(member.getUser()), serverUser.getServerId());
|
||||
postTargetService.sendTextInPostTarget(text, LoggingPostTarget.LEAVE_LOG, serverUser.getServerId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeatureDefinition getFeature() {
|
||||
return ModerationFeatureDefinition.LOGGING;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DefaultListenerResult execute(MemberLeaveModel model) {
|
||||
String text = templateService.renderTemplateWithMap(USER_LEAVE_TEMPLATE, getUserParameter(model.getMember().getUser()), model.getLeavingUser().getServerId());
|
||||
postTargetService.sendTextInPostTarget(text, LoggingPostTarget.LEAVE_LOG, model.getServerId());
|
||||
return DefaultListenerResult.PROCESSED;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
package dev.sheldan.abstracto.moderation.listener;
|
||||
|
||||
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 dev.sheldan.abstracto.core.service.ChannelService;
|
||||
import dev.sheldan.abstracto.core.service.MemberService;
|
||||
import dev.sheldan.abstracto.core.service.PostTargetService;
|
||||
@@ -58,10 +60,12 @@ public class MessageDeleteLogListener implements AsyncMessageDeletedListener {
|
||||
private MessageDeleteLogListener self;
|
||||
|
||||
@Override
|
||||
public void execute(CachedMessage messageFromCache) {
|
||||
memberService.getMemberInServerAsync(messageFromCache.getServerId(), messageFromCache.getAuthor().getAuthorId()).thenAccept(member ->
|
||||
self.executeListener(messageFromCache, member)
|
||||
public DefaultListenerResult execute(MessageDeletedModel model) {
|
||||
CachedMessage message = model.getCachedMessage();
|
||||
memberService.getMemberInServerAsync(model.getServerId(), message.getAuthor().getAuthorId()).thenAccept(member ->
|
||||
self.executeListener(message, member)
|
||||
);
|
||||
return DefaultListenerResult.PROCESSED;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
package dev.sheldan.abstracto.moderation.listener;
|
||||
|
||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
import dev.sheldan.abstracto.core.listener.DefaultListenerResult;
|
||||
import dev.sheldan.abstracto.core.listener.async.jda.AsyncMessageTextUpdatedListener;
|
||||
import dev.sheldan.abstracto.core.models.cache.CachedMessage;
|
||||
import dev.sheldan.abstracto.core.models.listener.MessageTextUpdatedModel;
|
||||
import dev.sheldan.abstracto.core.service.ChannelService;
|
||||
import dev.sheldan.abstracto.core.service.MemberService;
|
||||
import dev.sheldan.abstracto.core.service.PostTargetService;
|
||||
@@ -12,6 +14,7 @@ import dev.sheldan.abstracto.moderation.model.template.listener.MessageEditedLog
|
||||
import dev.sheldan.abstracto.core.templating.model.MessageToSend;
|
||||
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
import net.dv8tion.jda.api.entities.TextChannel;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
@@ -35,29 +38,26 @@ public class MessageEditedListener implements AsyncMessageTextUpdatedListener {
|
||||
private ChannelService channelService;
|
||||
|
||||
@Override
|
||||
public void execute(CachedMessage messageBefore, CachedMessage messageAfter) {
|
||||
if(messageBefore.getContent().equals(messageAfter.getContent())) {
|
||||
public DefaultListenerResult execute(MessageTextUpdatedModel model) {
|
||||
Message messageAfter = model.getAfter();
|
||||
CachedMessage messageBefore = model.getBefore();
|
||||
if(messageBefore.getContent().equals(messageAfter.getContentRaw())) {
|
||||
log.trace("Message content was the same. Possible reason was: message was not in cache.");
|
||||
return;
|
||||
return DefaultListenerResult.IGNORED;
|
||||
}
|
||||
memberService.getMemberInServerAsync(messageAfter.getServerId(), messageAfter.getAuthor().getAuthorId()).thenAccept(author -> {
|
||||
log.trace("Message {} in channel {} in guild {} was edited.", messageBefore.getMessageId(), messageBefore.getChannelId(), messageBefore.getServerId());
|
||||
TextChannel textChannel = channelService.getTextChannelFromServer(messageAfter.getServerId(), messageAfter.getChannelId());
|
||||
MessageEditedLog log = MessageEditedLog
|
||||
.builder()
|
||||
.messageAfter(messageAfter)
|
||||
.messageBefore(messageBefore)
|
||||
.messageChannel(textChannel)
|
||||
.guild(textChannel.getGuild())
|
||||
.member(author)
|
||||
.build();
|
||||
MessageToSend message = templateService.renderEmbedTemplate(MESSAGE_EDITED_TEMPLATE, log, messageBefore.getServerId());
|
||||
postTargetService.sendEmbedInPostTarget(message, LoggingPostTarget.EDIT_LOG, messageBefore.getServerId());
|
||||
}).exceptionally(throwable -> {
|
||||
log.error("Failed to load member {} for message edited listener in server {} for message {} in channel {}.",
|
||||
messageAfter.getAuthor().getAuthorId(), messageAfter.getServerId(), messageAfter.getMessageId(), messageAfter.getChannelId(), throwable);
|
||||
return null;
|
||||
});
|
||||
log.trace("Message {} in channel {} in guild {} was edited.", messageBefore.getMessageId(), messageBefore.getChannelId(), messageBefore.getServerId());
|
||||
TextChannel textChannel = channelService.getTextChannelFromServer(model.getServerId(), messageBefore.getChannelId());
|
||||
MessageEditedLog log = MessageEditedLog
|
||||
.builder()
|
||||
.messageAfter(messageAfter)
|
||||
.messageBefore(messageBefore)
|
||||
.messageChannel(textChannel)
|
||||
.guild(textChannel.getGuild())
|
||||
.member(messageAfter.getMember())
|
||||
.build();
|
||||
MessageToSend message = templateService.renderEmbedTemplate(MESSAGE_EDITED_TEMPLATE, log, messageBefore.getServerId());
|
||||
postTargetService.sendEmbedInPostTarget(message, LoggingPostTarget.EDIT_LOG, messageBefore.getServerId());
|
||||
return DefaultListenerResult.PROCESSED;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -44,8 +44,7 @@ public class MuteManagementServiceBean implements MuteManagementService {
|
||||
.muteId(id)
|
||||
.muteEnded(false)
|
||||
.build();
|
||||
muteRepository.save(mute);
|
||||
return mute;
|
||||
return muteRepository.save(mute);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -30,8 +30,7 @@ public class MuteRoleManagementServiceBean implements MuteRoleManagementService
|
||||
.role(role)
|
||||
.roleServer(server)
|
||||
.build();
|
||||
muteRoleRepository.save(muteRole);
|
||||
return muteRole;
|
||||
return muteRoleRepository.save(muteRole);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -36,8 +36,7 @@ public class UserNoteManagementServiceBean implements UserNoteManagementService
|
||||
.server(aUserInAServer.getServerReference())
|
||||
.user(aUserInAServer)
|
||||
.build();
|
||||
userNoteRepository.save(newNote);
|
||||
return newNote;
|
||||
return userNoteRepository.save(newNote);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -35,8 +35,7 @@ public class WarnManagementServiceBean implements WarnManagementService {
|
||||
.warnId(warningId)
|
||||
.decayed(false)
|
||||
.build();
|
||||
warnRepository.save(warning);
|
||||
return warning;
|
||||
return warnRepository.save(warning);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
package dev.sheldan.abstracto.moderation.listener;
|
||||
|
||||
import dev.sheldan.abstracto.core.execution.result.MessageReceivedListenerResult;
|
||||
import dev.sheldan.abstracto.core.listener.ConsumableListenerResult;
|
||||
import dev.sheldan.abstracto.core.metric.service.MetricService;
|
||||
import dev.sheldan.abstracto.core.models.ServerUser;
|
||||
import dev.sheldan.abstracto.core.models.listener.MessageReceivedModel;
|
||||
import dev.sheldan.abstracto.core.service.FeatureModeService;
|
||||
import dev.sheldan.abstracto.core.service.MessageService;
|
||||
import dev.sheldan.abstracto.core.service.PostTargetService;
|
||||
@@ -68,6 +69,9 @@ public class InviteLinkFilterListenerTest {
|
||||
@Mock
|
||||
private MetricService metricService;
|
||||
|
||||
@Mock
|
||||
private MessageReceivedModel model;
|
||||
|
||||
private static final Long SERVER_ID = 1L;
|
||||
private static final Long CHANNEL_ID = 2L;
|
||||
private static final Long USER_ID = 3L;
|
||||
@@ -79,8 +83,9 @@ public class InviteLinkFilterListenerTest {
|
||||
public void testExecutionWithNoInvite() {
|
||||
when(message.getContentRaw()).thenReturn("text");
|
||||
setupBasicMessage();
|
||||
MessageReceivedListenerResult result = testUnit.execute(message);
|
||||
Assert.assertEquals(MessageReceivedListenerResult.PROCESSED, result);
|
||||
when(model.getMessage()).thenReturn(message);
|
||||
ConsumableListenerResult result = testUnit.execute(model);
|
||||
Assert.assertEquals(ConsumableListenerResult.PROCESSED, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -88,8 +93,9 @@ public class InviteLinkFilterListenerTest {
|
||||
when(message.getContentRaw()).thenReturn(INVITE_LINK);
|
||||
when(inviteLinkFilterService.isCodeFiltered(eq(INVITE_CODE), any(ServerUser.class))).thenReturn(false);
|
||||
setupBasicMessage();
|
||||
MessageReceivedListenerResult result = testUnit.execute(message);
|
||||
Assert.assertEquals(MessageReceivedListenerResult.PROCESSED, result);
|
||||
when(model.getMessage()).thenReturn(message);
|
||||
ConsumableListenerResult result = testUnit.execute(model);
|
||||
Assert.assertEquals(ConsumableListenerResult.PROCESSED, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -100,8 +106,9 @@ public class InviteLinkFilterListenerTest {
|
||||
when(featureModeService.featureModeActive(ModerationFeatureDefinition.INVITE_FILTER, SERVER_ID, InviteFilterMode.TRACK_USES)).thenReturn(false);
|
||||
when(featureModeService.featureModeActive(ModerationFeatureDefinition.INVITE_FILTER, SERVER_ID, InviteFilterMode.FILTER_NOTIFICATIONS)).thenReturn(false);
|
||||
setupBasicMessage();
|
||||
MessageReceivedListenerResult result = testUnit.execute(message);
|
||||
Assert.assertEquals(MessageReceivedListenerResult.DELETED, result);
|
||||
when(model.getMessage()).thenReturn(message);
|
||||
ConsumableListenerResult result = testUnit.execute(model);
|
||||
Assert.assertEquals(ConsumableListenerResult.DELETED, result);
|
||||
verify(metricService, times(1)).incrementCounter(any());
|
||||
}
|
||||
|
||||
@@ -113,8 +120,9 @@ public class InviteLinkFilterListenerTest {
|
||||
when(featureModeService.featureModeActive(ModerationFeatureDefinition.INVITE_FILTER, SERVER_ID, InviteFilterMode.TRACK_USES)).thenReturn(true);
|
||||
when(featureModeService.featureModeActive(ModerationFeatureDefinition.INVITE_FILTER, SERVER_ID, InviteFilterMode.FILTER_NOTIFICATIONS)).thenReturn(false);
|
||||
setupBasicMessage();
|
||||
MessageReceivedListenerResult result = testUnit.execute(message);
|
||||
Assert.assertEquals(MessageReceivedListenerResult.DELETED, result);
|
||||
when(model.getMessage()).thenReturn(message);
|
||||
ConsumableListenerResult result = testUnit.execute(model);
|
||||
Assert.assertEquals(ConsumableListenerResult.DELETED, result);
|
||||
verifyTracking();
|
||||
verify(metricService, times(1)).incrementCounter(any());
|
||||
}
|
||||
@@ -128,8 +136,9 @@ public class InviteLinkFilterListenerTest {
|
||||
when(featureModeService.featureModeActive(ModerationFeatureDefinition.INVITE_FILTER, SERVER_ID, InviteFilterMode.FILTER_NOTIFICATIONS)).thenReturn(true);
|
||||
setupForNotification();
|
||||
setupBasicMessage();
|
||||
MessageReceivedListenerResult result = testUnit.execute(message);
|
||||
Assert.assertEquals(MessageReceivedListenerResult.DELETED, result);
|
||||
when(model.getMessage()).thenReturn(message);
|
||||
ConsumableListenerResult result = testUnit.execute(model);
|
||||
Assert.assertEquals(ConsumableListenerResult.DELETED, result);
|
||||
verifyTracking();
|
||||
verify(metricService, times(1)).incrementCounter(any());
|
||||
}
|
||||
@@ -143,9 +152,10 @@ public class InviteLinkFilterListenerTest {
|
||||
when(featureModeService.featureModeActive(ModerationFeatureDefinition.INVITE_FILTER, SERVER_ID, InviteFilterMode.FILTER_NOTIFICATIONS)).thenReturn(true);
|
||||
setupForNotification();
|
||||
setupBasicMessage();
|
||||
MessageReceivedListenerResult result = testUnit.execute(message);
|
||||
when(model.getMessage()).thenReturn(message);
|
||||
ConsumableListenerResult result = testUnit.execute(model);
|
||||
verify(metricService, times(1)).incrementCounter(any());
|
||||
Assert.assertEquals(MessageReceivedListenerResult.DELETED, result);
|
||||
Assert.assertEquals(ConsumableListenerResult.DELETED, result);
|
||||
verify(inviteLinkFilterService, times(0)).storeFilteredInviteLinkUsage(eq(INVITE_CODE), any(ServerUser.class));
|
||||
}
|
||||
|
||||
@@ -158,9 +168,10 @@ public class InviteLinkFilterListenerTest {
|
||||
when(featureModeService.featureModeActive(ModerationFeatureDefinition.INVITE_FILTER, SERVER_ID, InviteFilterMode.FILTER_NOTIFICATIONS)).thenReturn(true);
|
||||
when(postTargetService.postTargetDefinedInServer(InviteFilterPostTarget.INVITE_DELETE_LOG, SERVER_ID)).thenReturn(false);
|
||||
setupBasicMessage();
|
||||
MessageReceivedListenerResult result = testUnit.execute(message);
|
||||
when(model.getMessage()).thenReturn(message);
|
||||
ConsumableListenerResult result = testUnit.execute(model);
|
||||
verify(metricService, times(1)).incrementCounter(any());
|
||||
Assert.assertEquals(MessageReceivedListenerResult.DELETED, result);
|
||||
Assert.assertEquals(ConsumableListenerResult.DELETED, result);
|
||||
verify(inviteLinkFilterService, times(0)).storeFilteredInviteLinkUsage(eq(INVITE_CODE), any(ServerUser.class));
|
||||
verify(templateService, times(0)).renderEmbedTemplate(eq(InviteLinkFilterListener.INVITE_LINK_DELETED_NOTIFICATION_EMBED_TEMPLATE_KEY), any(DeletedInvitesNotificationModel.class), eq(SERVER_ID));
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package dev.sheldan.abstracto.moderation.listener;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.ServerUser;
|
||||
import dev.sheldan.abstracto.core.models.listener.MemberJoinModel;
|
||||
import dev.sheldan.abstracto.core.service.MemberService;
|
||||
import dev.sheldan.abstracto.core.service.PostTargetService;
|
||||
import dev.sheldan.abstracto.moderation.config.posttarget.LoggingPostTarget;
|
||||
@@ -40,6 +41,8 @@ public class JoinLoggerTest {
|
||||
@Mock
|
||||
private Member member;
|
||||
|
||||
@Mock
|
||||
private MemberJoinModel model;
|
||||
|
||||
private static final Long SERVER_ID = 1L;
|
||||
private static final Long USER_ID = 2L;
|
||||
@@ -48,17 +51,13 @@ public class JoinLoggerTest {
|
||||
public void testExecute() {
|
||||
when(serverUser.getUserId()).thenReturn(USER_ID);
|
||||
when(serverUser.getServerId()).thenReturn(SERVER_ID);
|
||||
when(model.getMember()).thenReturn(member);
|
||||
when(memberService.getMemberInServerAsync(SERVER_ID, USER_ID)).thenReturn(CompletableFuture.completedFuture(member));
|
||||
testUnit.execute(serverUser);
|
||||
verify(self, times(1)).sendJoinLog(serverUser, member);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testJoinLog() {
|
||||
String message = "text";
|
||||
testUnit.execute(model);
|
||||
when(serverUser.getServerId()).thenReturn(SERVER_ID);
|
||||
String message = "text";
|
||||
when(templateService.renderTemplateWithMap(eq(JoinLogger.USER_JOIN_TEMPLATE), any(), eq(SERVER_ID))).thenReturn(message);
|
||||
testUnit.sendJoinLog(serverUser, member);
|
||||
verify(postTargetService, times(1)).sendTextInPostTarget(message, LoggingPostTarget.JOIN_LOG, SERVER_ID);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package dev.sheldan.abstracto.moderation.listener;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.ServerUser;
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.core.models.listener.MemberJoinModel;
|
||||
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
|
||||
import dev.sheldan.abstracto.moderation.service.MuteService;
|
||||
import dev.sheldan.abstracto.moderation.service.management.MuteManagementService;
|
||||
@@ -42,6 +43,9 @@ public class JoinMuteListenerTest {
|
||||
@Mock
|
||||
private ServerUser serverUser;
|
||||
|
||||
@Mock
|
||||
private MemberJoinModel model;
|
||||
|
||||
private static final Long SERVER_ID = 3L;
|
||||
private static final Long USER_ID = 4L;
|
||||
|
||||
@@ -51,7 +55,8 @@ public class JoinMuteListenerTest {
|
||||
when(serverUser.getUserId()).thenReturn(USER_ID);
|
||||
when(userInServerManagementService.loadOrCreateUser(SERVER_ID, USER_ID)).thenReturn(joiningUser);
|
||||
when(muteManagementService.hasActiveMute(joiningUser)).thenReturn(false);
|
||||
testUnit.execute(serverUser);
|
||||
when(model.getMember()).thenReturn(member);
|
||||
testUnit.execute(model);
|
||||
verify(muteService, times(0)).applyMuteRole(joiningUser);
|
||||
}
|
||||
|
||||
@@ -61,7 +66,8 @@ public class JoinMuteListenerTest {
|
||||
when(serverUser.getUserId()).thenReturn(USER_ID);
|
||||
when(userInServerManagementService.loadOrCreateUser(SERVER_ID, USER_ID)).thenReturn(joiningUser);
|
||||
when(muteManagementService.hasActiveMute(joiningUser)).thenReturn(true);
|
||||
testUnit.execute(serverUser);
|
||||
when(model.getMember()).thenReturn(member);
|
||||
testUnit.execute(model);
|
||||
verify(muteService, times(1)).applyMuteRole(joiningUser);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package dev.sheldan.abstracto.moderation.listener;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.ServerUser;
|
||||
import dev.sheldan.abstracto.core.models.listener.MemberLeaveModel;
|
||||
import dev.sheldan.abstracto.core.service.MemberService;
|
||||
import dev.sheldan.abstracto.core.service.PostTargetService;
|
||||
import dev.sheldan.abstracto.moderation.config.posttarget.LoggingPostTarget;
|
||||
@@ -42,6 +43,9 @@ public class LeaveLoggerTest {
|
||||
@Mock
|
||||
private Member member;
|
||||
|
||||
@Mock
|
||||
private MemberLeaveModel model;
|
||||
|
||||
private static final Long SERVER_ID = 1L;
|
||||
private static final Long USER_ID = 2L;
|
||||
|
||||
@@ -50,19 +54,14 @@ public class LeaveLoggerTest {
|
||||
when(leavingUser.getUserId()).thenReturn(USER_ID);
|
||||
when(leavingUser.getServerId()).thenReturn(SERVER_ID);
|
||||
when(memberService.getMemberInServerAsync(SERVER_ID, USER_ID)).thenReturn(CompletableFuture.completedFuture(member));
|
||||
testUnit.execute(leavingUser);
|
||||
verify(self, times(1)).executeJoinLogging(leavingUser, member);
|
||||
when(model.getMember()).thenReturn(member);
|
||||
User user = Mockito.mock(User.class);
|
||||
when(member.getUser()).thenReturn(user);
|
||||
String message = "text";
|
||||
when(leavingUser.getServerId()).thenReturn(SERVER_ID);
|
||||
when(templateService.renderTemplateWithMap(eq(LeaveLogger.USER_LEAVE_TEMPLATE), any(), eq(SERVER_ID))).thenReturn(message);
|
||||
testUnit.execute(model);
|
||||
verify(postTargetService, times(1)).sendTextInPostTarget(message, LoggingPostTarget.LEAVE_LOG, SERVER_ID);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void executeListener() {
|
||||
User user = Mockito.mock(User.class);
|
||||
when(member.getUser()).thenReturn(user);
|
||||
String message = "text";
|
||||
when(leavingUser.getServerId()).thenReturn(SERVER_ID);
|
||||
when(templateService.renderTemplateWithMap(eq(LeaveLogger.USER_LEAVE_TEMPLATE), any(), eq(SERVER_ID))).thenReturn(message);
|
||||
testUnit.executeJoinLogging(leavingUser, member);
|
||||
verify(postTargetService, times(1)).sendTextInPostTarget(message, LoggingPostTarget.LEAVE_LOG, SERVER_ID);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package dev.sheldan.abstracto.moderation.listener;
|
||||
import dev.sheldan.abstracto.core.models.cache.CachedAttachment;
|
||||
import dev.sheldan.abstracto.core.models.cache.CachedAuthor;
|
||||
import dev.sheldan.abstracto.core.models.cache.CachedMessage;
|
||||
import dev.sheldan.abstracto.core.models.listener.MessageDeletedModel;
|
||||
import dev.sheldan.abstracto.core.service.ChannelService;
|
||||
import dev.sheldan.abstracto.core.service.MemberService;
|
||||
import dev.sheldan.abstracto.core.service.PostTargetService;
|
||||
@@ -86,13 +87,18 @@ public class MessageDeleteLogListenerTest {
|
||||
@Mock
|
||||
private Guild guild;
|
||||
|
||||
@Mock
|
||||
private MessageDeletedModel model;
|
||||
|
||||
@Test
|
||||
public void testExecuteListener() {
|
||||
when(deletedMessage.getAuthor()).thenReturn(cachedAuthor);
|
||||
when(cachedAuthor.getAuthorId()).thenReturn(AUTHOR_ID);
|
||||
when(deletedMessage.getServerId()).thenReturn(SERVER_ID);
|
||||
when(memberService.getMemberInServerAsync(SERVER_ID, AUTHOR_ID)).thenReturn(CompletableFuture.completedFuture(member));
|
||||
testUnit.execute(deletedMessage);
|
||||
when(model.getCachedMessage()).thenReturn(deletedMessage);
|
||||
when(model.getServerId()).thenReturn(SERVER_ID);
|
||||
testUnit.execute(model);
|
||||
verify(self, times(1)).executeListener(deletedMessage, member);
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ package dev.sheldan.abstracto.moderation.listener;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.cache.CachedAuthor;
|
||||
import dev.sheldan.abstracto.core.models.cache.CachedMessage;
|
||||
import dev.sheldan.abstracto.core.models.listener.MessageTextUpdatedModel;
|
||||
import dev.sheldan.abstracto.core.service.ChannelService;
|
||||
import dev.sheldan.abstracto.core.service.MemberService;
|
||||
import dev.sheldan.abstracto.core.service.PostTargetService;
|
||||
@@ -11,6 +12,7 @@ import dev.sheldan.abstracto.core.templating.model.MessageToSend;
|
||||
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
||||
import net.dv8tion.jda.api.entities.Guild;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
import net.dv8tion.jda.api.entities.TextChannel;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
@@ -44,11 +46,13 @@ public class MessageEditedListenerTest {
|
||||
private MemberService memberService;
|
||||
|
||||
@Mock
|
||||
private CachedMessage messageAfter;
|
||||
private Message messageAfter;
|
||||
|
||||
@Mock
|
||||
private CachedMessage messageBefore;
|
||||
|
||||
private MessageTextUpdatedModel model;
|
||||
|
||||
private static final Long SERVER_ID = 4L;
|
||||
private static final Long CHANNEL_ID = 5L;
|
||||
private static final Long AUTHOR_ID = 6L;
|
||||
@@ -56,9 +60,11 @@ public class MessageEditedListenerTest {
|
||||
@Test
|
||||
public void testExecuteListenerWithSameContent() {
|
||||
String content = "text";
|
||||
when(messageAfter.getContent()).thenReturn(content);
|
||||
when(messageAfter.getContentRaw()).thenReturn(content);
|
||||
when(messageBefore.getContent()).thenReturn(content);
|
||||
testUnit.execute(messageBefore, messageAfter);
|
||||
when(model.getAfter()).thenReturn(messageAfter);
|
||||
when(model.getBefore()).thenReturn(messageBefore);
|
||||
testUnit.execute(model);
|
||||
verify(templateService, times(0)).renderEmbedTemplate(eq(MessageEditedListener.MESSAGE_EDITED_TEMPLATE), any());
|
||||
}
|
||||
|
||||
@@ -67,15 +73,12 @@ public class MessageEditedListenerTest {
|
||||
String content = "text";
|
||||
String contentAfterwards = "text2";
|
||||
TextChannel channel = Mockito.mock(TextChannel.class);
|
||||
when(messageAfter.getContent()).thenReturn(contentAfterwards);
|
||||
when(messageAfter.getChannelId()).thenReturn(CHANNEL_ID);
|
||||
when(messageAfter.getContentRaw()).thenReturn(contentAfterwards);
|
||||
Guild guild = Mockito.mock(Guild.class);
|
||||
when(channel.getGuild()).thenReturn(guild);
|
||||
when(messageAfter.getServerId()).thenReturn(SERVER_ID);
|
||||
Member author = Mockito.mock(Member.class);
|
||||
CachedAuthor cachedAuthor = Mockito.mock(CachedAuthor.class);
|
||||
when(cachedAuthor.getAuthorId()).thenReturn(AUTHOR_ID);
|
||||
when(messageAfter.getAuthor()).thenReturn(cachedAuthor);
|
||||
when(messageBefore.getContent()).thenReturn(content);
|
||||
when(messageBefore.getServerId()).thenReturn(SERVER_ID);
|
||||
MessageToSend messageToSend = Mockito.mock(MessageToSend.class);
|
||||
@@ -83,7 +86,9 @@ public class MessageEditedListenerTest {
|
||||
when(templateService.renderEmbedTemplate(eq(MessageEditedListener.MESSAGE_EDITED_TEMPLATE), captor.capture(), eq(SERVER_ID))).thenReturn(messageToSend);
|
||||
when(memberService.getMemberInServerAsync(SERVER_ID, AUTHOR_ID)).thenReturn(CompletableFuture.completedFuture(author));
|
||||
when(channelService.getTextChannelFromServer(SERVER_ID, CHANNEL_ID)).thenReturn(channel);
|
||||
testUnit.execute(messageBefore, messageAfter);
|
||||
when(model.getAfter()).thenReturn(messageAfter);
|
||||
when(model.getBefore()).thenReturn(messageBefore);
|
||||
testUnit.execute(model);
|
||||
verify(postTargetService, times(1)).sendEmbedInPostTarget(messageToSend, LoggingPostTarget.EDIT_LOG, SERVER_ID);
|
||||
MessageEditedLog capturedValue = captor.getValue();
|
||||
Assert.assertEquals(messageBefore, capturedValue.getMessageBefore());
|
||||
|
||||
@@ -5,6 +5,7 @@ import dev.sheldan.abstracto.core.models.context.UserInitiatedServerContext;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.experimental.SuperBuilder;
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
|
||||
/**
|
||||
* Used when rendering the log message when a message was edited. The template is: "message_edited_embed"
|
||||
@@ -16,7 +17,7 @@ public class MessageEditedLog extends UserInitiatedServerContext {
|
||||
/**
|
||||
* The {@link CachedMessage} instance which contains the new content of the message
|
||||
*/
|
||||
private CachedMessage messageAfter;
|
||||
private Message messageAfter;
|
||||
|
||||
/**
|
||||
* The {@link CachedMessage} which contains the message before the edit was made
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
package dev.sheldan.abstracto.modmail.listener;
|
||||
|
||||
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 dev.sheldan.abstracto.core.service.MemberService;
|
||||
import dev.sheldan.abstracto.core.service.MessageService;
|
||||
import dev.sheldan.abstracto.modmail.config.ModMailFeatureDefinition;
|
||||
@@ -34,8 +36,9 @@ public class ModMailMessageDeletedListener implements AsyncMessageDeletedListene
|
||||
private MemberService memberService;
|
||||
|
||||
@Override
|
||||
public void execute(CachedMessage messageBefore) {
|
||||
Optional<ModMailMessage> messageOptional = modMailMessageManagementService.getByMessageIdOptional(messageBefore.getMessageId());
|
||||
public DefaultListenerResult execute(MessageDeletedModel model) {
|
||||
CachedMessage message = model.getCachedMessage();
|
||||
Optional<ModMailMessage> messageOptional = modMailMessageManagementService.getByMessageIdOptional(message.getMessageId());
|
||||
messageOptional.ifPresent(modMailMessage -> {
|
||||
ModMailThread thread = modMailMessage.getThreadReference();
|
||||
Long dmMessageId = modMailMessage.getCreatedMessageInDM();
|
||||
@@ -44,7 +47,7 @@ public class ModMailMessageDeletedListener implements AsyncMessageDeletedListene
|
||||
Long channelId = thread.getChannel().getId();
|
||||
Long serverId = thread.getServer().getId();
|
||||
log.info("Deleting message for mod mail thread {} in channel {} in server {}.", thread.getId(), channelId, serverId);
|
||||
memberService.getMemberInServerAsync(messageBefore.getServerId(), modMailMessage.getThreadReference().getUser().getUserReference().getId()).thenAccept(member -> {
|
||||
memberService.getMemberInServerAsync(model.getServerId(), modMailMessage.getThreadReference().getUser().getUserReference().getId()).thenAccept(member -> {
|
||||
CompletableFuture<Void> dmDeletePromise = messageService.deleteMessageInChannelWithUser(member.getUser(), dmMessageId);
|
||||
CompletableFuture<Void> channelDeletePromise;
|
||||
if(hasMessageInChannel) {
|
||||
@@ -53,11 +56,11 @@ public class ModMailMessageDeletedListener implements AsyncMessageDeletedListene
|
||||
channelDeletePromise = CompletableFuture.completedFuture(null);
|
||||
}
|
||||
CompletableFuture.allOf(dmDeletePromise, channelDeletePromise).whenComplete((unused, throwable) ->
|
||||
self.removeMessageFromThread(messageBefore.getMessageId())
|
||||
self.removeMessageFromThread(message.getMessageId())
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
return DefaultListenerResult.PROCESSED;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
|
||||
@@ -4,10 +4,12 @@ import dev.sheldan.abstracto.core.command.config.Parameters;
|
||||
import dev.sheldan.abstracto.core.command.service.CommandRegistry;
|
||||
import dev.sheldan.abstracto.core.command.service.CommandService;
|
||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
import dev.sheldan.abstracto.core.listener.DefaultListenerResult;
|
||||
import dev.sheldan.abstracto.core.listener.async.jda.AsyncMessageTextUpdatedListener;
|
||||
import dev.sheldan.abstracto.core.models.FullUserInServer;
|
||||
import dev.sheldan.abstracto.core.models.cache.CachedMessage;
|
||||
import dev.sheldan.abstracto.core.models.database.AChannel;
|
||||
import dev.sheldan.abstracto.core.models.listener.MessageTextUpdatedModel;
|
||||
import dev.sheldan.abstracto.core.service.ChannelService;
|
||||
import dev.sheldan.abstracto.core.service.MemberService;
|
||||
import dev.sheldan.abstracto.core.service.MessageService;
|
||||
@@ -62,34 +64,32 @@ public class ModMailMessageEditedListener implements AsyncMessageTextUpdatedList
|
||||
private ModMailThreadService modMailThreadService;
|
||||
|
||||
@Override
|
||||
public void execute(CachedMessage messageBefore, CachedMessage messageAfter) {
|
||||
public DefaultListenerResult execute(MessageTextUpdatedModel model) {
|
||||
CachedMessage messageBefore = model.getBefore();
|
||||
Message message = model.getAfter();
|
||||
if(!modMailThreadService.isModMailThread(messageBefore.getChannelId())) {
|
||||
return;
|
||||
return DefaultListenerResult.IGNORED;
|
||||
}
|
||||
|
||||
messageService.loadMessageFromCachedMessage(messageAfter).thenAccept(loadedMessage ->
|
||||
self.executeMessageUpdatedLogic(messageBefore, messageAfter, loadedMessage)
|
||||
);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void executeMessageUpdatedLogic(CachedMessage messageBefore, CachedMessage messageAfter, Message loadedMessage) {
|
||||
Optional<ModMailMessage> messageOptional = modMailMessageManagementService.getByMessageIdOptional(messageBefore.getMessageId());
|
||||
messageOptional.ifPresent(modMailMessage -> {
|
||||
log.info("Editing send message {} in channel {} in mod mail thread {} in server {}.", messageBefore.getMessageId(), messageBefore.getChannelId(), modMailMessage.getThreadReference().getId(), messageBefore.getServerId());
|
||||
String contentStripped = messageAfter.getContent();
|
||||
String commandName = commandRegistry.getCommandName(contentStripped.substring(0, contentStripped.indexOf(" ")), messageBefore.getServerId());
|
||||
if(!commandService.doesCommandExist(commandName)) {
|
||||
commandName = DEFAULT_COMMAND_FOR_MODMAIL_EDIT;
|
||||
log.info("Edit did not contain the original command to retrieve the parameters for. Resulting to {}.", DEFAULT_COMMAND_FOR_MODMAIL_EDIT);
|
||||
}
|
||||
CompletableFuture<Parameters> parameterParseFuture = commandService.getParametersForCommand(commandName, loadedMessage);
|
||||
CompletableFuture<Member> loadTargetUser = memberService.getMemberInServerAsync(messageBefore.getServerId(), modMailMessage.getThreadReference().getUser().getUserReference().getId());
|
||||
CompletableFuture<Member> loadEditingUser = memberService.getMemberInServerAsync(messageBefore.getServerId(), modMailMessage.getAuthor().getUserReference().getId());
|
||||
CompletableFuture.allOf(parameterParseFuture, loadTargetUser, loadEditingUser).thenAccept(unused ->
|
||||
self.updateMessageInThread(loadedMessage, parameterParseFuture.join(), loadTargetUser.join(), loadEditingUser.join())
|
||||
);
|
||||
});
|
||||
if(messageOptional.isPresent()) {
|
||||
messageOptional.ifPresent(modMailMessage -> {
|
||||
log.info("Editing send message {} in channel {} in mod mail thread {} in server {}.", messageBefore.getMessageId(), messageBefore.getChannelId(), modMailMessage.getThreadReference().getId(), messageBefore.getServerId());
|
||||
String contentStripped = message.getContentStripped();
|
||||
String commandName = commandRegistry.getCommandName(contentStripped.substring(0, contentStripped.indexOf(" ")), messageBefore.getServerId());
|
||||
if(!commandService.doesCommandExist(commandName)) {
|
||||
commandName = DEFAULT_COMMAND_FOR_MODMAIL_EDIT;
|
||||
log.info("Edit did not contain the original command to retrieve the parameters for. Resulting to {}.", DEFAULT_COMMAND_FOR_MODMAIL_EDIT);
|
||||
}
|
||||
CompletableFuture<Parameters> parameterParseFuture = commandService.getParametersForCommand(commandName, message);
|
||||
CompletableFuture<Member> loadTargetUser = memberService.getMemberInServerAsync(messageBefore.getServerId(), modMailMessage.getThreadReference().getUser().getUserReference().getId());
|
||||
CompletableFuture<Member> loadEditingUser = memberService.getMemberInServerAsync(messageBefore.getServerId(), modMailMessage.getAuthor().getUserReference().getId());
|
||||
CompletableFuture.allOf(parameterParseFuture, loadTargetUser, loadEditingUser).thenAccept(unused ->
|
||||
self.updateMessageInThread(message, parameterParseFuture.join(), loadTargetUser.join(), loadEditingUser.join())
|
||||
);
|
||||
});
|
||||
return DefaultListenerResult.PROCESSED;
|
||||
}
|
||||
return DefaultListenerResult.IGNORED;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
|
||||
@@ -37,8 +37,7 @@ public class ModMailMessageManagementServiceBean implements ModMailMessageManage
|
||||
log.info("Storing created message in DM {} with created message in channel {} caused by message {} to modmail thread {} of user {} in server {}.",
|
||||
dmId, channelMessageId, userPostedMessage.getId(), modMailThread.getId(), author.getUserReference().getId(), author.getServerReference().getId());
|
||||
|
||||
modMailMessageRepository.save(modMailMessage);
|
||||
return modMailMessage;
|
||||
return modMailMessageRepository.save(modMailMessage);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -39,8 +39,7 @@ public class ModMailSubscriberManagementServiceBean implements ModMailSubscriber
|
||||
|
||||
log.info("Creating subscription for user {} in server {} for modmail thread {}.",
|
||||
aUserInAServer.getUserReference().getId(), aUserInAServer.getServerReference().getId(), modMailThread.getId());
|
||||
modMailSubscriberRepository.save(subscriber);
|
||||
return subscriber;
|
||||
return modMailSubscriberRepository.save(subscriber);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -115,8 +115,7 @@ public class ModMailThreadManagementServiceBean implements ModMailThreadManageme
|
||||
log.info("Create modmail thread in channel {} for user {} in server {}.",
|
||||
channel.getId(), userInAServer.getUserReference().getId(), userInAServer.getServerReference().getId());
|
||||
|
||||
modMailThreadRepository.save(thread);
|
||||
return thread;
|
||||
return modMailThreadRepository.save(thread);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -5,6 +5,7 @@ import dev.sheldan.abstracto.core.models.database.AChannel;
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import dev.sheldan.abstracto.core.models.database.AUser;
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.core.models.listener.MessageDeletedModel;
|
||||
import dev.sheldan.abstracto.core.service.MemberService;
|
||||
import dev.sheldan.abstracto.core.service.MessageService;
|
||||
import dev.sheldan.abstracto.modmail.model.database.ModMailMessage;
|
||||
@@ -60,6 +61,9 @@ public class ModMailMessageDeletedListenerTest {
|
||||
@Mock
|
||||
private AChannel channel;
|
||||
|
||||
@Mock
|
||||
private MessageDeletedModel model;
|
||||
|
||||
private static final Long DELETED_MESSAGE_ID = 4L;
|
||||
private static final Long CREATED_MESSAGE_ID_1 = 3L;
|
||||
private static final Long CREATED_MESSAGE_ID_2 = 5L;
|
||||
@@ -71,7 +75,8 @@ public class ModMailMessageDeletedListenerTest {
|
||||
public void testDeleteOutSideOfThread() {
|
||||
when(deletedMessage.getMessageId()).thenReturn(DELETED_MESSAGE_ID);
|
||||
when(modMailMessageManagementService.getByMessageIdOptional(DELETED_MESSAGE_ID)).thenReturn(Optional.empty());
|
||||
testUnit.execute(deletedMessage);
|
||||
when(model.getCachedMessage()).thenReturn(deletedMessage);
|
||||
testUnit.execute(model);
|
||||
verify(memberService, times(0)).getMemberInServerAsync(anyLong(), anyLong());
|
||||
}
|
||||
|
||||
@@ -94,7 +99,8 @@ public class ModMailMessageDeletedListenerTest {
|
||||
when(targetMember.getUser()).thenReturn(targetUser);
|
||||
when(memberService.getMemberInServerAsync(SERVER_ID, USER_ID)).thenReturn(CompletableFuture.completedFuture(targetMember));
|
||||
when(messageService.deleteMessageInChannelWithUser(targetUser, CREATED_MESSAGE_ID_2)).thenReturn(CompletableFuture.completedFuture(null));
|
||||
testUnit.execute(deletedMessage);
|
||||
when(model.getCachedMessage()).thenReturn(deletedMessage);
|
||||
testUnit.execute(model);
|
||||
verify(messageService, times(0)).deleteMessageInChannelInServer(eq(SERVER_ID), anyLong(), any());
|
||||
verify(self, times(1)).removeMessageFromThread(DELETED_MESSAGE_ID);
|
||||
}
|
||||
@@ -121,7 +127,8 @@ public class ModMailMessageDeletedListenerTest {
|
||||
when(memberService.getMemberInServerAsync(SERVER_ID, USER_ID)).thenReturn(CompletableFuture.completedFuture(targetMember));
|
||||
when(messageService.deleteMessageInChannelWithUser(targetUser, CREATED_MESSAGE_ID_2)).thenReturn(CompletableFuture.completedFuture(null));
|
||||
when(messageService.deleteMessageInChannelInServer(SERVER_ID, CHANNEL_ID, CREATED_MESSAGE_ID_1)).thenReturn(CompletableFuture.completedFuture(null));
|
||||
testUnit.execute(deletedMessage);
|
||||
when(model.getCachedMessage()).thenReturn(deletedMessage);
|
||||
testUnit.execute(model);
|
||||
verify(self, times(1)).removeMessageFromThread(DELETED_MESSAGE_ID);
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ import dev.sheldan.abstracto.core.models.cache.CachedMessage;
|
||||
import dev.sheldan.abstracto.core.models.database.AChannel;
|
||||
import dev.sheldan.abstracto.core.models.database.AUser;
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.core.models.listener.MessageTextUpdatedModel;
|
||||
import dev.sheldan.abstracto.core.service.ChannelService;
|
||||
import dev.sheldan.abstracto.core.service.MemberService;
|
||||
import dev.sheldan.abstracto.core.service.MessageService;
|
||||
@@ -72,7 +73,7 @@ public class ModMailMessageEditedListenerTest {
|
||||
private CachedMessage messageBefore;
|
||||
|
||||
@Mock
|
||||
private CachedMessage messageAfter;
|
||||
private Message messageAfter;
|
||||
|
||||
@Mock
|
||||
private Message loadedMessage;
|
||||
@@ -101,6 +102,9 @@ public class ModMailMessageEditedListenerTest {
|
||||
@Captor
|
||||
private ArgumentCaptor<ModMailModeratorReplyModel> replyModelArgumentCaptor;
|
||||
|
||||
@Mock
|
||||
private MessageTextUpdatedModel model;
|
||||
|
||||
private static final Long CHANNEL_ID = 5L;
|
||||
private static final Long MESSAGE_ID = 6L;
|
||||
private static final Long CREATED_MESSAGE_ID = 10L;
|
||||
@@ -111,33 +115,26 @@ public class ModMailMessageEditedListenerTest {
|
||||
private static final Long USER_ID = 3L;
|
||||
private static final Long AUTHOR_USER_ID = 9L;
|
||||
|
||||
@Test
|
||||
public void testMessageLoading() {
|
||||
when(messageBefore.getChannelId()).thenReturn(CHANNEL_ID);
|
||||
when(modMailThreadService.isModMailThread(CHANNEL_ID)).thenReturn(true);
|
||||
when(messageService.loadMessageFromCachedMessage(messageAfter)).thenReturn(CompletableFuture.completedFuture(loadedMessage));
|
||||
testUnit.execute(messageBefore, messageAfter);
|
||||
verify(self, times(1)).executeMessageUpdatedLogic(messageBefore, messageAfter, loadedMessage);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEditOutsideModMailThread() {
|
||||
when(modMailThreadService.isModMailThread(CHANNEL_ID)).thenReturn(false);
|
||||
when(messageBefore.getChannelId()).thenReturn(CHANNEL_ID);
|
||||
testUnit.execute(messageBefore, messageAfter);
|
||||
when(model.getAfter()).thenReturn(messageAfter);
|
||||
when(model.getBefore()).thenReturn(messageBefore);
|
||||
testUnit.execute(model);
|
||||
verify(modMailMessageManagementService, times(0)).getByMessageIdOptional(anyLong());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEditNotTrackedMessage() {
|
||||
when(messageBefore.getMessageId()).thenReturn(MESSAGE_ID);
|
||||
when(modMailMessageManagementService.getByMessageIdOptional(MESSAGE_ID)).thenReturn(Optional.empty());
|
||||
testUnit.executeMessageUpdatedLogic(messageBefore, messageAfter, loadedMessage);
|
||||
verify(commandRegistry, times(0)).getCommandName(anyString(), anyLong());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEditMessageWithCorrectCommand() {
|
||||
when(messageBefore.getChannelId()).thenReturn(CHANNEL_ID);
|
||||
when(modMailThreadService.isModMailThread(CHANNEL_ID)).thenReturn(true);
|
||||
when(model.getBefore()).thenReturn(messageBefore);
|
||||
when(model.getAfter()).thenReturn(messageAfter);
|
||||
when(messageBefore.getMessageId()).thenReturn(MESSAGE_ID);
|
||||
when(modMailMessageManagementService.getByMessageIdOptional(MESSAGE_ID)).thenReturn(Optional.empty());
|
||||
when(messageBefore.getChannelId()).thenReturn(CHANNEL_ID);
|
||||
when(messageBefore.getMessageId()).thenReturn(MESSAGE_ID);
|
||||
when(messageBefore.getServerId()).thenReturn(SERVER_ID);
|
||||
@@ -154,14 +151,16 @@ public class ModMailMessageEditedListenerTest {
|
||||
AUser authorUser = Mockito.mock(AUser.class);
|
||||
when(authorUser.getId()).thenReturn(AUTHOR_USER_ID);
|
||||
when(authorUserInAServer.getUserReference()).thenReturn(authorUser);
|
||||
when(messageAfter.getContent()).thenReturn(NEW_CONTENT);
|
||||
when(messageAfter.getContentStripped()).thenReturn(NEW_CONTENT);
|
||||
when(commandRegistry.getCommandName(NEW_COMMAND_PART, SERVER_ID)).thenReturn(NEW_COMMAND_PART);
|
||||
when(commandService.doesCommandExist(NEW_COMMAND_PART)).thenReturn(true);
|
||||
when(commandService.getParametersForCommand(NEW_COMMAND_PART, loadedMessage)).thenReturn(CompletableFuture.completedFuture(parsedParameters));
|
||||
when(commandService.getParametersForCommand(NEW_COMMAND_PART, messageAfter)).thenReturn(CompletableFuture.completedFuture(parsedParameters));
|
||||
when(memberService.getMemberInServerAsync(SERVER_ID, USER_ID)).thenReturn(CompletableFuture.completedFuture(targetMember));
|
||||
when(memberService.getMemberInServerAsync(SERVER_ID, AUTHOR_USER_ID)).thenReturn(CompletableFuture.completedFuture(authorMember));
|
||||
testUnit.executeMessageUpdatedLogic(messageBefore, messageAfter, loadedMessage);
|
||||
verify(self, times(1)).updateMessageInThread(loadedMessage, parsedParameters, targetMember, authorMember);
|
||||
when(model.getAfter()).thenReturn(messageAfter);
|
||||
when(model.getBefore()).thenReturn(messageBefore);
|
||||
testUnit.execute(model);
|
||||
verify(self, times(1)).updateMessageInThread(messageAfter, parsedParameters, targetMember, authorMember);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -169,6 +168,7 @@ public class ModMailMessageEditedListenerTest {
|
||||
when(messageBefore.getChannelId()).thenReturn(CHANNEL_ID);
|
||||
when(messageBefore.getMessageId()).thenReturn(MESSAGE_ID);
|
||||
when(messageBefore.getServerId()).thenReturn(SERVER_ID);
|
||||
when(modMailThreadService.isModMailThread(CHANNEL_ID)).thenReturn(true);
|
||||
when(modMailMessageManagementService.getByMessageIdOptional(MESSAGE_ID)).thenReturn(Optional.of(modMailMessage));
|
||||
ModMailThread thread = Mockito.mock(ModMailThread.class);
|
||||
when(modMailMessage.getThreadReference()).thenReturn(thread);
|
||||
@@ -182,14 +182,16 @@ public class ModMailMessageEditedListenerTest {
|
||||
AUser authorUser = Mockito.mock(AUser.class);
|
||||
when(authorUser.getId()).thenReturn(AUTHOR_USER_ID);
|
||||
when(authorUserInAServer.getUserReference()).thenReturn(authorUser);
|
||||
when(messageAfter.getContent()).thenReturn(NEW_CONTENT);
|
||||
when(messageAfter.getContentStripped()).thenReturn(NEW_CONTENT);
|
||||
when(commandRegistry.getCommandName(NEW_COMMAND_PART, SERVER_ID)).thenReturn(NEW_COMMAND_PART);
|
||||
when(commandService.doesCommandExist(NEW_COMMAND_PART)).thenReturn(false);
|
||||
when(commandService.getParametersForCommand(DEFAULT_COMMAND_FOR_MODMAIL_EDIT, loadedMessage)).thenReturn(CompletableFuture.completedFuture(parsedParameters));
|
||||
when(commandService.getParametersForCommand(DEFAULT_COMMAND_FOR_MODMAIL_EDIT, messageAfter)).thenReturn(CompletableFuture.completedFuture(parsedParameters));
|
||||
when(memberService.getMemberInServerAsync(SERVER_ID, USER_ID)).thenReturn(CompletableFuture.completedFuture(targetMember));
|
||||
when(memberService.getMemberInServerAsync(SERVER_ID, AUTHOR_USER_ID)).thenReturn(CompletableFuture.completedFuture(authorMember));
|
||||
testUnit.executeMessageUpdatedLogic(messageBefore, messageAfter, loadedMessage);
|
||||
verify(self, times(1)).updateMessageInThread(loadedMessage, parsedParameters, targetMember, authorMember);
|
||||
when(model.getAfter()).thenReturn(messageAfter);
|
||||
when(model.getBefore()).thenReturn(messageBefore);
|
||||
testUnit.execute(model);
|
||||
verify(self, times(1)).updateMessageInThread(messageAfter, parsedParameters, targetMember, authorMember);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -35,8 +35,7 @@ public class ReminderManagementServiceBean implements ReminderManagementService
|
||||
log.info("Creating reminder for user {} in server {} in message {} to be reminded at {}.",
|
||||
userToBeReminded.getAUserInAServer().getUserReference().getId(), userToBeReminded.getGuild().getId(), messageId, timeToBeRemindedAt);
|
||||
|
||||
reminderRepository.save(reminder);
|
||||
return reminder;
|
||||
return reminderRepository.save(reminder);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
package dev.sheldan.abstracto.repostdetection.listener;
|
||||
|
||||
import dev.sheldan.abstracto.core.listener.DefaultListenerResult;
|
||||
import dev.sheldan.abstracto.core.listener.sync.entity.AsyncChannelGroupCreatedListener;
|
||||
import dev.sheldan.abstracto.core.models.database.AChannelGroup;
|
||||
import dev.sheldan.abstracto.core.models.listener.ChannelGroupCreatedListenerModel;
|
||||
import dev.sheldan.abstracto.core.service.management.ChannelGroupManagementService;
|
||||
import dev.sheldan.abstracto.repostdetection.service.RepostServiceBean;
|
||||
import dev.sheldan.abstracto.repostdetection.service.management.RepostCheckChannelGroupManagement;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class RepostCheckAsyncChannelGroupCreatedListener implements AsyncChannelGroupCreatedListener {
|
||||
|
||||
@Autowired
|
||||
private RepostCheckChannelGroupManagement checkChannelGroupManagement;
|
||||
|
||||
@Autowired
|
||||
private ChannelGroupManagementService channelGroupManagementService;
|
||||
|
||||
@Override
|
||||
public DefaultListenerResult execute(ChannelGroupCreatedListenerModel model) {
|
||||
AChannelGroup channelGroup = channelGroupManagementService.findChannelGroupById(model.getChannelGroupId());
|
||||
if(channelGroup.getChannelGroupType().getGroupTypeKey().equals(RepostServiceBean.REPOST_CHECK_CHANNEL_GROUP_TYPE)) {
|
||||
checkChannelGroupManagement.createRepostCheckChannelGroup(channelGroup);
|
||||
return DefaultListenerResult.PROCESSED;
|
||||
}
|
||||
return DefaultListenerResult.IGNORED;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package dev.sheldan.abstracto.repostdetection.listener;
|
||||
|
||||
import dev.sheldan.abstracto.core.listener.DefaultListenerResult;
|
||||
import dev.sheldan.abstracto.core.listener.sync.entity.AsyncChannelGroupDeletedListener;
|
||||
import dev.sheldan.abstracto.core.models.database.AChannelGroup;
|
||||
import dev.sheldan.abstracto.core.models.listener.ChannelGroupDeletedListenerModel;
|
||||
import dev.sheldan.abstracto.core.service.management.ChannelGroupManagementService;
|
||||
import dev.sheldan.abstracto.repostdetection.service.RepostServiceBean;
|
||||
import dev.sheldan.abstracto.repostdetection.service.management.RepostCheckChannelGroupManagement;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class RepostCheckAsyncChannelGroupDeletedListener implements AsyncChannelGroupDeletedListener {
|
||||
|
||||
@Autowired
|
||||
private RepostCheckChannelGroupManagement checkChannelGroupManagement;
|
||||
|
||||
@Autowired
|
||||
private ChannelGroupManagementService channelGroupManagementService;
|
||||
|
||||
@Override
|
||||
public DefaultListenerResult execute(ChannelGroupDeletedListenerModel model) {
|
||||
AChannelGroup channelGroup = channelGroupManagementService.findChannelGroupById(model.getChannelGroupId());
|
||||
if(channelGroup.getChannelGroupType().getGroupTypeKey().equals(RepostServiceBean.REPOST_CHECK_CHANNEL_GROUP_TYPE)) {
|
||||
checkChannelGroupManagement.deleteRepostCheckChannelGroup(channelGroup);
|
||||
return DefaultListenerResult.PROCESSED;
|
||||
}
|
||||
return DefaultListenerResult.IGNORED;
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
package dev.sheldan.abstracto.repostdetection.listener;
|
||||
|
||||
import dev.sheldan.abstracto.core.listener.sync.entity.ChannelGroupCreatedListener;
|
||||
import dev.sheldan.abstracto.core.models.database.AChannelGroup;
|
||||
import dev.sheldan.abstracto.repostdetection.service.RepostServiceBean;
|
||||
import dev.sheldan.abstracto.repostdetection.service.management.RepostCheckChannelGroupManagement;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class RepostCheckChannelGroupCreatedListener implements ChannelGroupCreatedListener {
|
||||
|
||||
@Autowired
|
||||
private RepostCheckChannelGroupManagement checkChannelGroupManagement;
|
||||
|
||||
@Override
|
||||
public void channelGroupCreated(AChannelGroup channelGroup) {
|
||||
if(channelGroup.getChannelGroupType().getGroupTypeKey().equals(RepostServiceBean.REPOST_CHECK_CHANNEL_GROUP_TYPE)) {
|
||||
checkChannelGroupManagement.createRepostCheckChannelGroup(channelGroup);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
package dev.sheldan.abstracto.repostdetection.listener;
|
||||
|
||||
import dev.sheldan.abstracto.core.listener.sync.entity.ChannelGroupDeletedListener;
|
||||
import dev.sheldan.abstracto.core.models.database.AChannelGroup;
|
||||
import dev.sheldan.abstracto.repostdetection.service.RepostServiceBean;
|
||||
import dev.sheldan.abstracto.repostdetection.service.management.RepostCheckChannelGroupManagement;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class RepostCheckChannelGroupDeletedListener implements ChannelGroupDeletedListener {
|
||||
|
||||
@Autowired
|
||||
private RepostCheckChannelGroupManagement checkChannelGroupManagement;
|
||||
|
||||
@Override
|
||||
public void channelGroupDeleted(AChannelGroup channelGroup) {
|
||||
if(channelGroup.getChannelGroupType().getGroupTypeKey().equals(RepostServiceBean.REPOST_CHECK_CHANNEL_GROUP_TYPE)) {
|
||||
checkChannelGroupManagement.deleteRepostCheckChannelGroup(channelGroup);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package dev.sheldan.abstracto.repostdetection.listener;
|
||||
|
||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
import dev.sheldan.abstracto.core.listener.DefaultListenerResult;
|
||||
import dev.sheldan.abstracto.core.listener.async.jda.AsyncMessageEmbeddedListener;
|
||||
import dev.sheldan.abstracto.core.models.database.AChannel;
|
||||
import dev.sheldan.abstracto.core.models.listener.GuildMessageEmbedEventModel;
|
||||
@@ -39,13 +40,13 @@ public class RepostEmbedListener implements AsyncMessageEmbeddedListener {
|
||||
private ChannelService channelService;
|
||||
|
||||
@Override
|
||||
public void execute(GuildMessageEmbedEventModel eventModel) {
|
||||
public DefaultListenerResult execute(GuildMessageEmbedEventModel eventModel) {
|
||||
AChannel channel = channelManagementService.loadChannel(eventModel.getChannelId());
|
||||
if(repostCheckChannelService.duplicateCheckEnabledForChannel(channel)) {
|
||||
if(repostManagement.messageEmbedsHaveBeenCovered(eventModel.getMessageId())) {
|
||||
log.info("The embeds of the message {} in channel {} in server {} have already been covered by repost check -- ignoring.",
|
||||
eventModel.getMessageId(), eventModel.getChannelId(), eventModel.getServerId());
|
||||
return;
|
||||
return DefaultListenerResult.IGNORED;
|
||||
}
|
||||
channelService.retrieveMessageInChannel(eventModel.getServerId(), eventModel.getChannelId(), eventModel.getMessageId()).thenAccept(message -> {
|
||||
List<MessageEmbed> imageEmbeds = eventModel.getEmbeds().stream().filter(messageEmbed -> messageEmbed.getType().equals(EmbedType.IMAGE)).collect(Collectors.toList());
|
||||
@@ -54,6 +55,7 @@ public class RepostEmbedListener implements AsyncMessageEmbeddedListener {
|
||||
}
|
||||
});
|
||||
}
|
||||
return DefaultListenerResult.PROCESSED;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,16 +1,18 @@
|
||||
package dev.sheldan.abstracto.repostdetection.listener;
|
||||
|
||||
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.cache.CachedEmbed;
|
||||
import dev.sheldan.abstracto.core.models.cache.CachedMessage;
|
||||
import dev.sheldan.abstracto.core.models.database.AChannel;
|
||||
import dev.sheldan.abstracto.core.models.listener.MessageReceivedModel;
|
||||
import dev.sheldan.abstracto.core.service.management.ChannelManagementService;
|
||||
import dev.sheldan.abstracto.repostdetection.config.RepostDetectionFeatureDefinition;
|
||||
import dev.sheldan.abstracto.repostdetection.service.RepostCheckChannelService;
|
||||
import dev.sheldan.abstracto.repostdetection.service.RepostService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.dv8tion.jda.api.entities.EmbedType;
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
import net.dv8tion.jda.api.entities.MessageEmbed;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@@ -32,13 +34,16 @@ public class RepostMessageReceivedListener implements AsyncMessageReceivedListen
|
||||
private ChannelManagementService channelManagementService;
|
||||
|
||||
@Override
|
||||
public void execute(CachedMessage message) {
|
||||
AChannel channel = channelManagementService.loadChannel(message.getChannelId());
|
||||
public DefaultListenerResult execute(MessageReceivedModel model) {
|
||||
Message message = model.getMessage();
|
||||
AChannel channel = channelManagementService.loadChannel(message.getTextChannel().getIdLong());
|
||||
if(repostCheckChannelService.duplicateCheckEnabledForChannel(channel)) {
|
||||
repostService.processMessageAttachmentRepostCheck(message);
|
||||
List<CachedEmbed> imageEmbeds = message.getEmbeds().stream().filter(messageEmbed -> messageEmbed.getType().equals(EmbedType.IMAGE)).collect(Collectors.toList());
|
||||
List<MessageEmbed> imageEmbeds = message.getEmbeds().stream().filter(messageEmbed -> messageEmbed.getType().equals(EmbedType.IMAGE)).collect(Collectors.toList());
|
||||
repostService.processMessageEmbedsRepostCheck(imageEmbeds, message);
|
||||
return DefaultListenerResult.PROCESSED;
|
||||
}
|
||||
return DefaultListenerResult.IGNORED;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -172,6 +172,18 @@ public class RepostServiceBean implements RepostService {
|
||||
return checkForDuplicates(serverChannelMessageUser, index, attachment.getProxyUrl());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<PostedImage> getRepostFor(Message message, Message.Attachment attachment, Integer index) {
|
||||
ServerChannelMessageUser serverChannelMessageUser = ServerChannelMessageUser
|
||||
.builder()
|
||||
.serverId(message.getGuild().getIdLong())
|
||||
.channelId(message.getChannel().getIdLong())
|
||||
.userId(message.getAuthor().getIdLong())
|
||||
.messageId(message.getIdLong())
|
||||
.build();
|
||||
return checkForDuplicates(serverChannelMessageUser, index, attachment.getProxyUrl());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String calculateHashForPost(String url, Long serverId) {
|
||||
File downloadedFile = null;
|
||||
@@ -204,6 +216,14 @@ public class RepostServiceBean implements RepostService {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processMessageAttachmentRepostCheck(Message message) {
|
||||
boolean canThereBeMultipleReposts = message.getAttachments().size() > 1;
|
||||
for (int imageIndex = 0; imageIndex < message.getAttachments().size(); imageIndex++) {
|
||||
executeRepostCheckForAttachment(message, message.getAttachments().get(imageIndex), imageIndex, canThereBeMultipleReposts);
|
||||
}
|
||||
}
|
||||
|
||||
private void executeRepostCheckForAttachment(CachedMessage message, CachedAttachment attachment, Integer index, boolean moreRepostsPossible) {
|
||||
Optional<PostedImage> originalPostOptional = getRepostFor(message, attachment, index);
|
||||
ServerChannelMessageUser serverChannelMessageUser = ServerChannelMessageUser
|
||||
@@ -216,6 +236,18 @@ public class RepostServiceBean implements RepostService {
|
||||
originalPostOptional.ifPresent(postedImage -> markMessageAndPersist(serverChannelMessageUser, index, moreRepostsPossible, postedImage));
|
||||
}
|
||||
|
||||
private void executeRepostCheckForAttachment(Message message, Message.Attachment attachment, Integer index, boolean moreRepostsPossible) {
|
||||
Optional<PostedImage> originalPostOptional = getRepostFor(message, attachment, index);
|
||||
ServerChannelMessageUser serverChannelMessageUser = ServerChannelMessageUser
|
||||
.builder()
|
||||
.serverId(message.getGuild().getIdLong())
|
||||
.channelId(message.getChannel().getIdLong())
|
||||
.userId(message.getAuthor().getIdLong())
|
||||
.messageId(message.getIdLong())
|
||||
.build();
|
||||
originalPostOptional.ifPresent(postedImage -> markMessageAndPersist(serverChannelMessageUser, index, moreRepostsPossible, postedImage));
|
||||
}
|
||||
|
||||
private void markMessageAndPersist(ServerChannelMessageUser messageUser, Integer index, boolean moreRepostsPossible, PostedImage originalPost) {
|
||||
log.info("Detected repost in message embed {} of message {} in channel {} in server {}.", index, messageUser.getMessageId(), messageUser.getChannelId(), messageUser.getServerId());
|
||||
CompletableFuture<Void> markerFuture = reactionService.addReactionToMessageAsync(REPOST_MARKER_EMOTE_KEY, messageUser.getServerId(), messageUser.getChannelId(), messageUser.getMessageId());
|
||||
|
||||
@@ -34,8 +34,7 @@ public class PostedImageManagementBean implements PostedImageManagement {
|
||||
.postedChannel(creation.getChannel())
|
||||
.build();
|
||||
|
||||
postedImageRepository.save(post);
|
||||
return post;
|
||||
return postedImageRepository.save(post);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -49,8 +49,7 @@ public class RepostCheckChannelGroupManagementBean implements RepostCheckChannel
|
||||
.id(channelGroup.getId())
|
||||
.build();
|
||||
|
||||
repository.save(repostCheckChannelGroup);
|
||||
return repostCheckChannelGroup;
|
||||
return repository.save(repostCheckChannelGroup);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -32,8 +32,7 @@ public class RepostManagementServiceBean implements RepostManagementService {
|
||||
.count(1)
|
||||
.build();
|
||||
|
||||
repostRepository.save(repost);
|
||||
return repost;
|
||||
return repostRepository.save(repost);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
package dev.sheldan.abstracto.repostdetection.listener;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.exception.ChannelGroupNotFoundByIdException;
|
||||
import dev.sheldan.abstracto.core.models.database.AChannelGroup;
|
||||
import dev.sheldan.abstracto.core.models.database.ChannelGroupType;
|
||||
import dev.sheldan.abstracto.core.models.listener.ChannelGroupCreatedListenerModel;
|
||||
import dev.sheldan.abstracto.core.service.management.ChannelGroupManagementService;
|
||||
import dev.sheldan.abstracto.repostdetection.service.RepostServiceBean;
|
||||
import dev.sheldan.abstracto.repostdetection.service.management.RepostCheckChannelGroupManagement;
|
||||
import org.junit.Test;
|
||||
@@ -13,35 +16,53 @@ import org.mockito.junit.MockitoJUnitRunner;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class RepostCheckChannelGroupCreatedListenerTest {
|
||||
public class RepostCheckAsyncChannelGroupCreatedListenerTest {
|
||||
|
||||
@InjectMocks
|
||||
private RepostCheckChannelGroupCreatedListener testUnit;
|
||||
private RepostCheckAsyncChannelGroupCreatedListener testUnit;
|
||||
|
||||
@Mock
|
||||
private RepostCheckChannelGroupManagement checkChannelGroupManagement;
|
||||
|
||||
@Mock
|
||||
private ChannelGroupManagementService channelGroupManagementService;
|
||||
|
||||
@Mock
|
||||
private AChannelGroup channelGroup;
|
||||
|
||||
@Mock
|
||||
private ChannelGroupCreatedListenerModel model;
|
||||
|
||||
@Mock
|
||||
private ChannelGroupType channelGroupType;
|
||||
|
||||
private static final String INCORRECT_TYPE = "incorrectType";
|
||||
private static final Long CHANNEL_GROUP_ID = 1L;
|
||||
|
||||
@Test
|
||||
public void testChannelGroupCreated() {
|
||||
when(channelGroup.getChannelGroupType()).thenReturn(channelGroupType);
|
||||
when(channelGroupType.getGroupTypeKey()).thenReturn(RepostServiceBean.REPOST_CHECK_CHANNEL_GROUP_TYPE);
|
||||
testUnit.channelGroupCreated(channelGroup);
|
||||
when(model.getChannelGroupId()).thenReturn(CHANNEL_GROUP_ID);
|
||||
when(channelGroupManagementService.findChannelGroupById(CHANNEL_GROUP_ID)).thenReturn(channelGroup);
|
||||
testUnit.execute(model);
|
||||
verify(checkChannelGroupManagement, times(1)).createRepostCheckChannelGroup(channelGroup);
|
||||
}
|
||||
|
||||
@Test(expected = ChannelGroupNotFoundByIdException.class)
|
||||
public void testChannelGroupNotExisting() {
|
||||
when(model.getChannelGroupId()).thenReturn(CHANNEL_GROUP_ID);
|
||||
when(channelGroupManagementService.findChannelGroupById(CHANNEL_GROUP_ID)).thenThrow(new ChannelGroupNotFoundByIdException());
|
||||
testUnit.execute(model);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testChannelGroupCreatedIncorrectType() {
|
||||
when(channelGroup.getChannelGroupType()).thenReturn(channelGroupType);
|
||||
when(channelGroupType.getGroupTypeKey()).thenReturn(INCORRECT_TYPE);
|
||||
testUnit.channelGroupCreated(channelGroup);
|
||||
when(model.getChannelGroupId()).thenReturn(CHANNEL_GROUP_ID);
|
||||
when(channelGroupManagementService.findChannelGroupById(CHANNEL_GROUP_ID)).thenReturn(channelGroup);
|
||||
testUnit.execute(model);
|
||||
verify(checkChannelGroupManagement, times(0)).createRepostCheckChannelGroup(channelGroup);
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,10 @@
|
||||
package dev.sheldan.abstracto.repostdetection.listener;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.exception.ChannelGroupNotFoundByIdException;
|
||||
import dev.sheldan.abstracto.core.models.database.AChannelGroup;
|
||||
import dev.sheldan.abstracto.core.models.database.ChannelGroupType;
|
||||
import dev.sheldan.abstracto.core.models.listener.ChannelGroupDeletedListenerModel;
|
||||
import dev.sheldan.abstracto.core.service.management.ChannelGroupManagementService;
|
||||
import dev.sheldan.abstracto.repostdetection.service.RepostServiceBean;
|
||||
import dev.sheldan.abstracto.repostdetection.service.management.RepostCheckChannelGroupManagement;
|
||||
import org.junit.Test;
|
||||
@@ -13,35 +16,53 @@ import org.mockito.junit.MockitoJUnitRunner;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class RepostCheckChannelGroupDeletedListenerTest {
|
||||
public class RepostCheckAsyncChannelGroupDeletedListenerTest {
|
||||
|
||||
@InjectMocks
|
||||
private RepostCheckChannelGroupDeletedListener testUnit;
|
||||
private RepostCheckAsyncChannelGroupDeletedListener testUnit;
|
||||
|
||||
@Mock
|
||||
private RepostCheckChannelGroupManagement checkChannelGroupManagement;
|
||||
|
||||
@Mock
|
||||
private ChannelGroupManagementService channelGroupManagementService;
|
||||
|
||||
@Mock
|
||||
private AChannelGroup channelGroup;
|
||||
|
||||
@Mock
|
||||
private ChannelGroupType channelGroupType;
|
||||
|
||||
@Mock
|
||||
private ChannelGroupDeletedListenerModel model;
|
||||
|
||||
private static final String INCORRECT_TYPE = "incorrectType";
|
||||
private static final Long CHANNEL_GROUP_ID = 1L;
|
||||
|
||||
@Test
|
||||
public void testChannelGroupDeleted() {
|
||||
when(channelGroup.getChannelGroupType()).thenReturn(channelGroupType);
|
||||
when(channelGroupType.getGroupTypeKey()).thenReturn(RepostServiceBean.REPOST_CHECK_CHANNEL_GROUP_TYPE);
|
||||
testUnit.channelGroupDeleted(channelGroup);
|
||||
when(model.getChannelGroupId()).thenReturn(CHANNEL_GROUP_ID);
|
||||
when(channelGroupManagementService.findChannelGroupById(CHANNEL_GROUP_ID)).thenReturn(channelGroup);
|
||||
testUnit.execute(model);
|
||||
verify(checkChannelGroupManagement, times(1)).deleteRepostCheckChannelGroup(channelGroup);
|
||||
}
|
||||
|
||||
@Test(expected = ChannelGroupNotFoundByIdException.class)
|
||||
public void testChannelGroupNotExisting() {
|
||||
when(model.getChannelGroupId()).thenReturn(CHANNEL_GROUP_ID);
|
||||
when(channelGroupManagementService.findChannelGroupById(CHANNEL_GROUP_ID)).thenThrow(new ChannelGroupNotFoundByIdException());
|
||||
testUnit.execute(model);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testChannelGroupDeletedIncorrectType() {
|
||||
when(channelGroup.getChannelGroupType()).thenReturn(channelGroupType);
|
||||
when(channelGroupType.getGroupTypeKey()).thenReturn(INCORRECT_TYPE);
|
||||
testUnit.channelGroupDeleted(channelGroup);
|
||||
when(model.getChannelGroupId()).thenReturn(CHANNEL_GROUP_ID);
|
||||
when(channelGroupManagementService.findChannelGroupById(CHANNEL_GROUP_ID)).thenReturn(channelGroup);
|
||||
testUnit.execute(model);
|
||||
verify(checkChannelGroupManagement, times(0)).deleteRepostCheckChannelGroup(channelGroup);
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,14 @@
|
||||
package dev.sheldan.abstracto.repostdetection.listener;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.cache.CachedEmbed;
|
||||
import dev.sheldan.abstracto.core.models.cache.CachedMessage;
|
||||
import dev.sheldan.abstracto.core.models.database.AChannel;
|
||||
import dev.sheldan.abstracto.core.models.listener.MessageReceivedModel;
|
||||
import dev.sheldan.abstracto.core.service.management.ChannelManagementService;
|
||||
import dev.sheldan.abstracto.repostdetection.service.RepostCheckChannelService;
|
||||
import dev.sheldan.abstracto.repostdetection.service.RepostService;
|
||||
import net.dv8tion.jda.api.entities.EmbedType;
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
import net.dv8tion.jda.api.entities.MessageEmbed;
|
||||
import net.dv8tion.jda.api.entities.TextChannel;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
@@ -34,27 +36,33 @@ public class RepostMessageReceivedListenerTest {
|
||||
private RepostService repostService;
|
||||
|
||||
@Mock
|
||||
private CachedMessage message;
|
||||
private Message message;
|
||||
|
||||
@Mock
|
||||
private AChannel channel;
|
||||
|
||||
@Mock
|
||||
private MessageReceivedModel model;
|
||||
|
||||
@Mock
|
||||
private TextChannel textChannel;
|
||||
|
||||
@Captor
|
||||
private ArgumentCaptor<List<CachedEmbed>> embedListCaptor;
|
||||
private ArgumentCaptor<List<MessageEmbed>> embedListCaptor;
|
||||
|
||||
private static final Long CHANNEL_ID = 4L;
|
||||
|
||||
@Test
|
||||
public void testExecuteCheckDisabled() {
|
||||
setupRepostCheckEnabled(false);
|
||||
testUnit.execute(message);
|
||||
testUnit.execute(model);
|
||||
verify(repostService, times(0)).processMessageAttachmentRepostCheck(message);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExecuteOnlyMessage() {
|
||||
setupRepostCheckEnabled(true);
|
||||
testUnit.execute(message);
|
||||
testUnit.execute(model);
|
||||
verify(repostService, times(1)).processMessageAttachmentRepostCheck(message);
|
||||
verify(repostService, times(1)).processMessageEmbedsRepostCheck(embedListCaptor.capture(), eq(message));
|
||||
Assert.assertEquals(0, embedListCaptor.getValue().size());
|
||||
@@ -63,35 +71,38 @@ public class RepostMessageReceivedListenerTest {
|
||||
@Test
|
||||
public void testExecuteOnlyMessageOneImageAttachment() {
|
||||
setupRepostCheckEnabled(true);
|
||||
CachedEmbed imageEmbed = Mockito.mock(CachedEmbed.class);
|
||||
MessageEmbed imageEmbed = Mockito.mock(MessageEmbed.class);
|
||||
when(imageEmbed.getType()).thenReturn(EmbedType.IMAGE);
|
||||
when(message.getEmbeds()).thenReturn(Arrays.asList(imageEmbed));
|
||||
testUnit.execute(message);
|
||||
testUnit.execute(model);
|
||||
verifySingleEmbed(imageEmbed);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExecuteOnlyMessageTwoEmbedsOneImageAttachment() {
|
||||
setupRepostCheckEnabled(true);
|
||||
CachedEmbed imageEmbed = Mockito.mock(CachedEmbed.class);
|
||||
MessageEmbed imageEmbed = Mockito.mock(MessageEmbed.class);
|
||||
when(imageEmbed.getType()).thenReturn(EmbedType.IMAGE);
|
||||
CachedEmbed nonImageEmbed = Mockito.mock(CachedEmbed.class);
|
||||
MessageEmbed nonImageEmbed = Mockito.mock(MessageEmbed.class);
|
||||
when(nonImageEmbed.getType()).thenReturn(EmbedType.LINK);
|
||||
when(message.getEmbeds()).thenReturn(Arrays.asList(imageEmbed, nonImageEmbed));
|
||||
testUnit.execute(message);
|
||||
when(model.getMessage()).thenReturn(message);
|
||||
testUnit.execute(model);
|
||||
verifySingleEmbed(imageEmbed);
|
||||
}
|
||||
|
||||
private void setupRepostCheckEnabled(boolean b) {
|
||||
when(message.getChannelId()).thenReturn(CHANNEL_ID);
|
||||
when(message.getTextChannel()).thenReturn(textChannel);
|
||||
when(model.getMessage()).thenReturn(message);
|
||||
when(textChannel.getIdLong()).thenReturn(CHANNEL_ID);
|
||||
when(channelManagementService.loadChannel(CHANNEL_ID)).thenReturn(channel);
|
||||
when(repostCheckChannelService.duplicateCheckEnabledForChannel(channel)).thenReturn(b);
|
||||
}
|
||||
|
||||
private void verifySingleEmbed(CachedEmbed imageEmbed) {
|
||||
private void verifySingleEmbed(MessageEmbed imageEmbed) {
|
||||
verify(repostService, times(1)).processMessageAttachmentRepostCheck(message);
|
||||
verify(repostService, times(1)).processMessageEmbedsRepostCheck(embedListCaptor.capture(), eq(message));
|
||||
List<CachedEmbed> processedEmbeds = embedListCaptor.getValue();
|
||||
List<MessageEmbed> processedEmbeds = embedListCaptor.getValue();
|
||||
Assert.assertEquals(1, processedEmbeds.size());
|
||||
Assert.assertEquals(imageEmbed, processedEmbeds.get(0));
|
||||
}
|
||||
|
||||
@@ -20,8 +20,10 @@ public interface RepostService {
|
||||
Optional<PostedImage> getRepostFor(Message message, MessageEmbed messageEmbed, Integer embedIndex);
|
||||
boolean isRepost(CachedMessage message, CachedAttachment attachment, Integer index);
|
||||
Optional<PostedImage> getRepostFor(CachedMessage message, CachedAttachment attachment, Integer index);
|
||||
Optional<PostedImage> getRepostFor(Message message, Message.Attachment attachment, Integer index);
|
||||
String calculateHashForPost(String url, Long serverId);
|
||||
void processMessageAttachmentRepostCheck(CachedMessage message);
|
||||
void processMessageAttachmentRepostCheck(Message message);
|
||||
void processMessageEmbedsRepostCheck(List<CachedEmbed> embeds, CachedMessage message);
|
||||
void processMessageEmbedsRepostCheck(List<MessageEmbed> embeds, Message message);
|
||||
CompletableFuture<List<RepostLeaderboardEntryModel>> retrieveRepostLeaderboard(Guild guild, Integer page);
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
package dev.sheldan.abstracto.starboard.config;
|
||||
|
||||
import dev.sheldan.abstracto.core.service.ExecutorService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.task.TaskExecutor;
|
||||
|
||||
@Configuration
|
||||
public class StarboardListenerConfig {
|
||||
@Autowired
|
||||
private ExecutorService executorService;
|
||||
|
||||
@Bean(name = "starboardStatusListenerExecutor")
|
||||
public TaskExecutor joinListenerExecutor() {
|
||||
return executorService.setupExecutorFor("starboardStatusListener");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package dev.sheldan.abstracto.starboard.listener;
|
||||
|
||||
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.metric.service.CounterMetric;
|
||||
import dev.sheldan.abstracto.core.metric.service.MetricTag;
|
||||
import dev.sheldan.abstracto.core.models.cache.CachedReactions;
|
||||
import dev.sheldan.abstracto.core.models.database.AEmote;
|
||||
import dev.sheldan.abstracto.core.models.listener.ReactionAddedModel;
|
||||
import dev.sheldan.abstracto.starboard.config.StarboardFeature;
|
||||
import dev.sheldan.abstracto.starboard.config.StarboardFeatureDefinition;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import java.util.Arrays;
|
||||
import java.util.Optional;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class StarAddedListener extends StarboardListener implements AsyncReactionAddedListener {
|
||||
|
||||
protected static final CounterMetric STARBOARD_STARS_ADDED = CounterMetric
|
||||
.builder()
|
||||
.name(STARBOARD_STARS)
|
||||
.tagList(Arrays.asList(MetricTag.getTag(STAR_ACTION, "added")))
|
||||
.build();
|
||||
|
||||
@Override
|
||||
public DefaultListenerResult execute(ReactionAddedModel model) {
|
||||
if(model.getUserReacting().getUserId().equals(model.getMessage().getAuthor().getAuthorId())) {
|
||||
return DefaultListenerResult.IGNORED;
|
||||
}
|
||||
Long serverId = model.getServerId();
|
||||
AEmote aEmote = emoteService.getEmoteOrDefaultEmote(StarboardFeature.STAR_EMOTE, serverId);
|
||||
if(emoteService.isReactionEmoteAEmote(model.getReaction().getReactionEmote(), aEmote)) {
|
||||
metricService.incrementCounter(STARBOARD_STARS_ADDED);
|
||||
log.info("User {} in server {} reacted with star to put a message {} from channel {} on starboard.",
|
||||
model.getUserReacting().getUserId(), model.getServerId(), model.getMessage().getMessageId(), model.getMessage().getChannelId());
|
||||
Optional<CachedReactions> reactionOptional = emoteService.getReactionFromMessageByEmote(model.getMessage(), aEmote);
|
||||
handleStarboardPostChange(model.getMessage(), reactionOptional.orElse(null), model.getUserReacting(), true);
|
||||
return DefaultListenerResult.PROCESSED;
|
||||
} else {
|
||||
return DefaultListenerResult.IGNORED;
|
||||
}
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
@Override
|
||||
public void postConstruct() {
|
||||
metricService.registerCounter(STARBOARD_STARS_ADDED, "Star reaction added");
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeatureDefinition getFeature() {
|
||||
return StarboardFeatureDefinition.STARBOARD;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package dev.sheldan.abstracto.starboard.listener;
|
||||
|
||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
import dev.sheldan.abstracto.core.listener.DefaultListenerResult;
|
||||
import dev.sheldan.abstracto.core.listener.async.jda.AsyncReactionClearedListener;
|
||||
import dev.sheldan.abstracto.core.models.listener.ReactionClearedModel;
|
||||
import dev.sheldan.abstracto.starboard.config.StarboardFeatureDefinition;
|
||||
import dev.sheldan.abstracto.starboard.model.database.StarboardPost;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class StarClearedListener extends StarboardListener implements AsyncReactionClearedListener {
|
||||
|
||||
@Override
|
||||
public DefaultListenerResult execute(ReactionClearedModel model) {
|
||||
Optional<StarboardPost> starboardPostOptional = starboardPostManagementService.findByMessageId(model.getMessage().getMessageId());
|
||||
|
||||
if(starboardPostOptional.isPresent()) {
|
||||
starboardPostOptional.ifPresent(starboardPost -> {
|
||||
log.info("Reactions on message {} in channel {} in server {} were cleared. Completely deleting the starboard post {}.",
|
||||
model.getMessage().getMessageId(), model.getMessage().getChannelId(), model.getServerId(), starboardPost.getId());
|
||||
starboardPostReactorManagementService.removeReactors(starboardPost);
|
||||
completelyRemoveStarboardPost(starboardPost, null);
|
||||
});
|
||||
return DefaultListenerResult.PROCESSED;
|
||||
}
|
||||
return DefaultListenerResult.IGNORED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeatureDefinition getFeature() {
|
||||
return StarboardFeatureDefinition.STARBOARD;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
package dev.sheldan.abstracto.starboard.listener;
|
||||
|
||||
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.metric.service.CounterMetric;
|
||||
import dev.sheldan.abstracto.core.metric.service.MetricTag;
|
||||
import dev.sheldan.abstracto.core.models.ServerUser;
|
||||
import dev.sheldan.abstracto.core.models.cache.CachedReactions;
|
||||
import dev.sheldan.abstracto.core.models.database.AEmote;
|
||||
import dev.sheldan.abstracto.core.models.listener.ReactionRemovedModel;
|
||||
import dev.sheldan.abstracto.starboard.config.StarboardFeature;
|
||||
import dev.sheldan.abstracto.starboard.config.StarboardFeatureDefinition;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import java.util.Arrays;
|
||||
import java.util.Optional;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class StarRemovedListener extends StarboardListener implements AsyncReactionRemovedListener {
|
||||
|
||||
protected static final CounterMetric STARBOARD_STARS_REMOVED = CounterMetric
|
||||
.builder()
|
||||
.name(STARBOARD_STARS)
|
||||
.tagList(Arrays.asList(MetricTag.getTag(STAR_ACTION, "removed")))
|
||||
.build();
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public DefaultListenerResult execute(ReactionRemovedModel model) {
|
||||
ServerUser userRemoving = model.getUserRemoving();
|
||||
if(model.getMessage().getAuthor().getAuthorId().equals(userRemoving.getUserId())) {
|
||||
return DefaultListenerResult.IGNORED;
|
||||
}
|
||||
Long guildId = model.getServerId();
|
||||
AEmote aEmote = emoteService.getEmoteOrDefaultEmote(StarboardFeature.STAR_EMOTE, guildId);
|
||||
if(emoteService.isReactionEmoteAEmote(model.getReaction().getReactionEmote(), aEmote)) {
|
||||
metricService.incrementCounter(STARBOARD_STARS_REMOVED);
|
||||
log.info("User {} in server {} removed star reaction from message {} on starboard.",
|
||||
userRemoving.getUserId(), model.getServerId(), model.getMessage().getMessageId());
|
||||
Optional<CachedReactions> reactionOptional = emoteService.getReactionFromMessageByEmote(model.getMessage(), aEmote);
|
||||
handleStarboardPostChange(model.getMessage(), reactionOptional.orElse(null), userRemoving, false);
|
||||
return DefaultListenerResult.PROCESSED;
|
||||
} else {
|
||||
return DefaultListenerResult.IGNORED;
|
||||
}
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
@Override
|
||||
public void postConstruct() {
|
||||
metricService.registerCounter(STARBOARD_STARS_REMOVED, "Star reaction removed");
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeatureDefinition getFeature() {
|
||||
return StarboardFeatureDefinition.STARBOARD;
|
||||
}
|
||||
}
|
||||
@@ -1,23 +1,15 @@
|
||||
package dev.sheldan.abstracto.starboard.listener;
|
||||
|
||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
import dev.sheldan.abstracto.core.listener.async.jda.AsyncReactionAddedListener;
|
||||
import dev.sheldan.abstracto.core.listener.async.jda.AsyncReactionClearedListener;
|
||||
import dev.sheldan.abstracto.core.listener.async.jda.AsyncReactionRemovedListener;
|
||||
import dev.sheldan.abstracto.core.metric.service.CounterMetric;
|
||||
import dev.sheldan.abstracto.core.metric.service.MetricService;
|
||||
import dev.sheldan.abstracto.core.metric.service.MetricTag;
|
||||
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.database.AEmote;
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.core.service.BotService;
|
||||
import dev.sheldan.abstracto.core.service.EmoteService;
|
||||
import dev.sheldan.abstracto.core.service.management.ConfigManagementService;
|
||||
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
|
||||
import dev.sheldan.abstracto.starboard.config.StarboardFeature;
|
||||
import dev.sheldan.abstracto.starboard.config.StarboardFeatureDefinition;
|
||||
import dev.sheldan.abstracto.starboard.model.database.StarboardPost;
|
||||
import dev.sheldan.abstracto.starboard.service.StarboardService;
|
||||
import dev.sheldan.abstracto.starboard.service.management.StarboardPostManagementService;
|
||||
@@ -25,7 +17,6 @@ import dev.sheldan.abstracto.starboard.service.management.StarboardPostReactorMa
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import java.util.Arrays;
|
||||
@@ -36,84 +27,54 @@ import java.util.stream.Collectors;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class StarboardListener implements AsyncReactionAddedListener, AsyncReactionRemovedListener, AsyncReactionClearedListener {
|
||||
public abstract class StarboardListener {
|
||||
|
||||
public static final String FIRST_LEVEL_THRESHOLD_KEY = "starLvl1";
|
||||
|
||||
@Autowired
|
||||
private BotService botService;
|
||||
protected ConfigManagementService configManagementService;
|
||||
|
||||
@Autowired
|
||||
private ConfigManagementService configManagementService;
|
||||
protected StarboardService starboardService;
|
||||
|
||||
@Autowired
|
||||
private StarboardService starboardService;
|
||||
protected StarboardPostManagementService starboardPostManagementService;
|
||||
|
||||
@Autowired
|
||||
private StarboardPostManagementService starboardPostManagementService;
|
||||
protected StarboardPostReactorManagementService starboardPostReactorManagementService;
|
||||
|
||||
@Autowired
|
||||
private StarboardPostReactorManagementService starboardPostReactorManagementService;
|
||||
protected UserInServerManagementService userInServerManagementService;
|
||||
|
||||
@Autowired
|
||||
private UserInServerManagementService userInServerManagementService;
|
||||
protected EmoteService emoteService;
|
||||
|
||||
@Autowired
|
||||
private EmoteService emoteService;
|
||||
|
||||
@Autowired
|
||||
private MetricService metricService;
|
||||
protected MetricService metricService;
|
||||
|
||||
public static final String STARBOARD_STARS = "starboard.stars";
|
||||
public static final String STARBOARD_POSTS = "starboard.posts";
|
||||
public static final String STAR_ACTION = "action";
|
||||
private static final CounterMetric STARBOARD_STARS_ADDED = CounterMetric
|
||||
.builder()
|
||||
.name(STARBOARD_STARS)
|
||||
.tagList(Arrays.asList(MetricTag.getTag(STAR_ACTION, "added")))
|
||||
.build();
|
||||
|
||||
private static final CounterMetric STARBOARD_STARS_REMOVED = CounterMetric
|
||||
.builder()
|
||||
.name(STARBOARD_STARS)
|
||||
.tagList(Arrays.asList(MetricTag.getTag(STAR_ACTION, "removed")))
|
||||
.build();
|
||||
|
||||
private static final CounterMetric STARBOARD_STARS_THRESHOLD_REACHED = CounterMetric
|
||||
protected static final CounterMetric STARBOARD_STARS_THRESHOLD_REACHED = CounterMetric
|
||||
.builder()
|
||||
.name(STARBOARD_POSTS)
|
||||
.tagList(Arrays.asList(MetricTag.getTag(STAR_ACTION, "threshold.reached")))
|
||||
.build();
|
||||
|
||||
private static final CounterMetric STARBOARD_STARS_THRESHOLD_FELL = CounterMetric
|
||||
protected static final CounterMetric STARBOARD_STARS_THRESHOLD_FELL = CounterMetric
|
||||
.builder()
|
||||
.name(STARBOARD_POSTS)
|
||||
.tagList(Arrays.asList(MetricTag.getTag(STAR_ACTION, "threshold.below")))
|
||||
.build();
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void executeReactionAdded(CachedMessage message, CachedReactions cachedReaction, ServerUser serverUser) {
|
||||
if(serverUser.getUserId().equals(message.getAuthor().getAuthorId())) {
|
||||
return;
|
||||
}
|
||||
Long guildId = message.getServerId();
|
||||
AEmote aEmote = emoteService.getEmoteOrDefaultEmote(StarboardFeature.STAR_EMOTE, guildId);
|
||||
if(emoteService.compareCachedEmoteWithAEmote(cachedReaction.getEmote(), aEmote)) {
|
||||
metricService.incrementCounter(STARBOARD_STARS_ADDED);
|
||||
log.info("User {} in server {} reacted with star to put a message {} from channel {} on starboard.", serverUser.getUserId(), message.getServerId(), message.getMessageId(), message.getChannelId());
|
||||
Optional<CachedReactions> reactionOptional = emoteService.getReactionFromMessageByEmote(message, aEmote);
|
||||
handleStarboardPostChange(message, reactionOptional.orElse(null), serverUser, true);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleStarboardPostChange(CachedMessage message, CachedReactions reaction, ServerUser serverUser, boolean adding) {
|
||||
protected void handleStarboardPostChange(CachedMessage message, CachedReactions reaction, ServerUser userReacting, boolean adding) {
|
||||
Optional<StarboardPost> starboardPostOptional = starboardPostManagementService.findByMessageId(message.getMessageId());
|
||||
if(reaction != null) {
|
||||
AUserInAServer author = userInServerManagementService.loadOrCreateUser(message.getServerId(), message.getAuthor().getAuthorId());
|
||||
List<AUserInAServer> userExceptAuthor = getUsersExcept(reaction.getUsers(), author);
|
||||
Long starMinimum = getFromConfig(FIRST_LEVEL_THRESHOLD_KEY, message.getServerId());
|
||||
AUserInAServer userAddingReaction = userInServerManagementService.loadOrCreateUser(serverUser);
|
||||
AUserInAServer userAddingReaction = userInServerManagementService.loadOrCreateUser(userReacting);
|
||||
if (userExceptAuthor.size() >= starMinimum) {
|
||||
log.info("Post reached starboard minimum. Message {} in channel {} in server {} will be starred/updated.",
|
||||
message.getMessageId(), message.getChannelId(), message.getServerId());
|
||||
@@ -122,24 +83,27 @@ public class StarboardListener implements AsyncReactionAddedListener, AsyncReact
|
||||
} else {
|
||||
metricService.incrementCounter(STARBOARD_STARS_THRESHOLD_REACHED);
|
||||
log.info("Creating starboard post for message {} in channel {} in server {}", message.getMessageId(), message.getChannelId(), message.getServerId());
|
||||
starboardService.createStarboardPost(message, userExceptAuthor, userAddingReaction, author);
|
||||
starboardService.createStarboardPost(message, userExceptAuthor, userAddingReaction, author).exceptionally(throwable -> {
|
||||
log.error("Failed to persist starboard post for message {}.", message.getMessageId(), throwable);
|
||||
return null;
|
||||
});
|
||||
}
|
||||
} else {
|
||||
if(starboardPostOptional.isPresent()) {
|
||||
metricService.incrementCounter(STARBOARD_STARS_THRESHOLD_FELL);
|
||||
log.info("Removing starboard post for message {} in channel {} in server {}. It fell under the threshold {}", message.getMessageId(), message.getChannelId(), message.getServerId(), starMinimum);
|
||||
starboardPostOptional.ifPresent(this::completelyRemoveStarboardPost);
|
||||
starboardPostOptional.ifPresent(starboardPost -> completelyRemoveStarboardPost(starboardPost, userReacting));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if(starboardPostOptional.isPresent()) {
|
||||
log.info("Removing starboard post for message {} in channel {} in server {}", message.getMessageId(), message.getChannelId(), message.getServerId());
|
||||
starboardPostOptional.ifPresent(this::completelyRemoveStarboardPost);
|
||||
starboardPostOptional.ifPresent(starboardPost -> completelyRemoveStarboardPost(starboardPost, userReacting));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void updateStarboardPost(CachedMessage message, AUserInAServer userReacting, boolean adding, StarboardPost starboardPost, List<AUserInAServer> userExceptAuthor) {
|
||||
protected void updateStarboardPost(CachedMessage message, AUserInAServer userReacting, boolean adding, StarboardPost starboardPost, List<AUserInAServer> userExceptAuthor) {
|
||||
starboardPost.setIgnored(false);
|
||||
// TODO handle futures correctly
|
||||
starboardService.updateStarboardPost(starboardPost, message, userExceptAuthor);
|
||||
@@ -152,62 +116,24 @@ public class StarboardListener implements AsyncReactionAddedListener, AsyncReact
|
||||
}
|
||||
}
|
||||
|
||||
private void completelyRemoveStarboardPost(StarboardPost starboardPost) {
|
||||
starboardService.deleteStarboardMessagePost(starboardPost);
|
||||
starboardPostManagementService.removePost(starboardPost);
|
||||
protected void completelyRemoveStarboardPost(StarboardPost starboardPost, ServerUser userReacting) {
|
||||
starboardService.deleteStarboardPost(starboardPost, userReacting);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void executeReactionRemoved(CachedMessage message, CachedReactions removedReaction, ServerUser userRemoving) {
|
||||
if(message.getAuthor().getAuthorId().equals(userRemoving.getUserId())) {
|
||||
return;
|
||||
}
|
||||
Long guildId = message.getServerId();
|
||||
AEmote aEmote = emoteService.getEmoteOrDefaultEmote(StarboardFeature.STAR_EMOTE, guildId);
|
||||
if(emoteService.compareCachedEmoteWithAEmote(removedReaction.getEmote(), aEmote)) {
|
||||
metricService.incrementCounter(STARBOARD_STARS_REMOVED);
|
||||
log.info("User {} in server {} removed star reaction from message {} on starboard.",
|
||||
userRemoving.getUserId(), message.getServerId(), message.getMessageId());
|
||||
Optional<CachedReactions> reactionOptional = emoteService.getReactionFromMessageByEmote(message, aEmote);
|
||||
handleStarboardPostChange(message, reactionOptional.orElse(null), userRemoving, false);
|
||||
}
|
||||
}
|
||||
|
||||
private Long getFromConfig(String key, Long guildId) {
|
||||
protected Long getFromConfig(String key, Long guildId) {
|
||||
return configManagementService.loadConfig(guildId, key).getLongValue();
|
||||
}
|
||||
|
||||
private List<AUserInAServer> getUsersExcept(List<ServerUser> users, AUserInAServer author) {
|
||||
protected List<AUserInAServer> getUsersExcept(List<ServerUser> users, AUserInAServer author) {
|
||||
return users.stream().filter(user -> !(user.getServerId().equals(author.getServerReference().getId()) && user.getUserId().equals(author.getUserReference().getId()))).map(serverUser -> {
|
||||
Optional<AUserInAServer> aUserInAServer = userInServerManagementService.loadUserOptional(serverUser.getServerId(), serverUser.getUserId());
|
||||
return aUserInAServer.orElse(null);
|
||||
}).filter(Objects::nonNull).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeatureDefinition getFeature() {
|
||||
return StarboardFeatureDefinition.STARBOARD;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void executeReactionCleared(CachedMessage message) {
|
||||
Optional<StarboardPost> starboardPostOptional = starboardPostManagementService.findByMessageId(message.getMessageId());
|
||||
|
||||
starboardPostOptional.ifPresent(starboardPost -> {
|
||||
log.info("Reactions on message {} in channel {} in server {} were cleared. Completely deleting the starboard post {}.",
|
||||
message.getMessageId(), message.getChannelId(), message.getServerId(), starboardPost.getId());
|
||||
starboardPostReactorManagementService.removeReactors(starboardPost);
|
||||
completelyRemoveStarboardPost(starboardPost);
|
||||
});
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void postConstruct() {
|
||||
metricService.registerCounter(STARBOARD_STARS_ADDED, "Star reaction added");
|
||||
metricService.registerCounter(STARBOARD_STARS_REMOVED, "Star reaction removed");
|
||||
metricService.registerCounter(STARBOARD_STARS_THRESHOLD_REACHED, "Starboard posts reaching threshold");
|
||||
metricService.registerCounter(STARBOARD_STARS_THRESHOLD_FELL, "Starboard posts falling below threshold");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
package dev.sheldan.abstracto.starboard.listener;
|
||||
|
||||
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 dev.sheldan.abstracto.starboard.config.StarboardFeatureDefinition;
|
||||
import dev.sheldan.abstracto.starboard.model.database.StarboardPost;
|
||||
import dev.sheldan.abstracto.starboard.service.management.StarboardPostManagementService;
|
||||
@@ -20,14 +22,16 @@ public class StarboardPostDeletedListener implements AsyncMessageDeletedListener
|
||||
private StarboardPostManagementService starboardPostManagementService;
|
||||
|
||||
@Override
|
||||
public void execute(CachedMessage messageBefore) {
|
||||
Optional<StarboardPost> byStarboardPostId = starboardPostManagementService.findByStarboardPostId(messageBefore.getMessageId());
|
||||
public DefaultListenerResult execute(MessageDeletedModel model) {
|
||||
CachedMessage message = model.getCachedMessage();
|
||||
Optional<StarboardPost> byStarboardPostId = starboardPostManagementService.findByStarboardPostId(message.getMessageId());
|
||||
if(byStarboardPostId.isPresent()) {
|
||||
StarboardPost post = byStarboardPostId.get();
|
||||
log.info("Removing starboard post: message {}, channel {}, server {}, because the message was deleted",
|
||||
post.getPostMessageId(), post.getSourceChannel().getId(), messageBefore.getServerId());
|
||||
starboardPostManagementService.setStarboardPostIgnored(messageBefore.getMessageId(), true);
|
||||
post.getPostMessageId(), post.getSourceChannel().getId(), message.getServerId());
|
||||
starboardPostManagementService.setStarboardPostIgnored(message.getMessageId(), true);
|
||||
}
|
||||
return DefaultListenerResult.PROCESSED;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
package dev.sheldan.abstracto.starboard.service;
|
||||
|
||||
import dev.sheldan.abstracto.core.listener.ListenerService;
|
||||
import dev.sheldan.abstracto.core.models.ServerChannelMessage;
|
||||
import dev.sheldan.abstracto.core.models.ServerUser;
|
||||
import dev.sheldan.abstracto.core.service.FeatureConfigService;
|
||||
import dev.sheldan.abstracto.core.service.FeatureFlagService;
|
||||
import dev.sheldan.abstracto.starboard.listener.StarboardPostState;
|
||||
import dev.sheldan.abstracto.starboard.listener.StarboardPostUpdatedListener;
|
||||
import dev.sheldan.abstracto.starboard.model.StarboardPostUpdatedModel;
|
||||
import dev.sheldan.abstracto.starboard.model.database.StarboardPost;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
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 java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class StarboardPostListenerManager {
|
||||
|
||||
@Autowired(required = false)
|
||||
private List<StarboardPostUpdatedListener> listeners;
|
||||
|
||||
@Autowired
|
||||
@Qualifier("starboardStatusListenerExecutor")
|
||||
private TaskExecutor starboardStatusExecutor;
|
||||
|
||||
@Autowired
|
||||
private StarboardPostListenerManager self;
|
||||
|
||||
@Autowired
|
||||
private FeatureConfigService featureConfigService;
|
||||
|
||||
@Autowired
|
||||
private FeatureFlagService featureFlagService;
|
||||
|
||||
@Autowired
|
||||
private ListenerService listenerService;
|
||||
|
||||
public void sendStarboardPostCreatedEvent(Long userReactingId, StarboardPost post) {
|
||||
if(listeners == null || listeners.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
ServerUser userReactingServerUser = ServerUser.builder().serverId(post.getServer().getId()).userId(userReactingId).build();
|
||||
StarboardPostUpdatedModel model = createStarboardStatusModel(post, userReactingServerUser);
|
||||
model.setNewState(StarboardPostState.CREATED);
|
||||
listeners.forEach(listener -> listenerService.executeFeatureAwareListener(listener, model));
|
||||
}
|
||||
|
||||
public void sendStarboardPostDeletedEvent(StarboardPost post, ServerUser userReacting) {
|
||||
if(listeners == null || listeners.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
StarboardPostUpdatedModel model = createStarboardStatusModel(post, userReacting);
|
||||
model.setNewState(StarboardPostState.DELETED);
|
||||
}
|
||||
|
||||
private StarboardPostUpdatedModel createStarboardStatusModel(StarboardPost post, ServerUser userReacting) {
|
||||
Long serverId = post.getServer().getId();
|
||||
ServerUser starredUser = ServerUser
|
||||
.builder()
|
||||
.serverId(serverId)
|
||||
.userId(post.getAuthor().getUserReference().getId())
|
||||
.build();
|
||||
ServerChannelMessage starboardMessagePayLoad = ServerChannelMessage
|
||||
.builder()
|
||||
.serverId(serverId)
|
||||
.channelId(post.getStarboardChannel().getId())
|
||||
.messageId(post.getStarboardMessageId())
|
||||
.build();
|
||||
|
||||
ServerChannelMessage starredMessage = ServerChannelMessage
|
||||
.builder()
|
||||
.serverId(serverId)
|
||||
.channelId(post.getSourceChannel().getId())
|
||||
.messageId(post.getPostMessageId())
|
||||
.build();
|
||||
|
||||
List<Long> starrerIds = post.
|
||||
getReactions()
|
||||
.stream()
|
||||
.map(starboardPostReaction -> starboardPostReaction.getReactor().getUserReference().getId())
|
||||
.collect(Collectors.toList());
|
||||
return StarboardPostUpdatedModel
|
||||
.builder()
|
||||
.lastStarrer(userReacting)
|
||||
.starredUser(starredUser)
|
||||
.starboardMessage(starboardMessagePayLoad)
|
||||
.starredMessage(starredMessage)
|
||||
.allStarrer(starrerIds)
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2,9 +2,9 @@ package dev.sheldan.abstracto.starboard.service;
|
||||
|
||||
import dev.sheldan.abstracto.core.exception.UserInServerNotFoundException;
|
||||
import dev.sheldan.abstracto.core.models.AServerAChannelMessage;
|
||||
import dev.sheldan.abstracto.core.models.ServerUser;
|
||||
import dev.sheldan.abstracto.core.models.cache.CachedMessage;
|
||||
import dev.sheldan.abstracto.core.models.database.AChannel;
|
||||
import dev.sheldan.abstracto.core.models.database.AUser;
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.core.models.database.PostTarget;
|
||||
import dev.sheldan.abstracto.core.models.property.SystemConfigProperty;
|
||||
@@ -13,9 +13,9 @@ import dev.sheldan.abstracto.core.service.management.ChannelManagementService;
|
||||
import dev.sheldan.abstracto.core.service.management.DefaultConfigManagementService;
|
||||
import dev.sheldan.abstracto.core.service.management.PostTargetManagement;
|
||||
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
|
||||
import dev.sheldan.abstracto.core.utils.FutureUtils;
|
||||
import dev.sheldan.abstracto.core.templating.model.MessageToSend;
|
||||
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
||||
import dev.sheldan.abstracto.core.utils.FutureUtils;
|
||||
import dev.sheldan.abstracto.starboard.config.StarboardFeature;
|
||||
import dev.sheldan.abstracto.starboard.config.StarboardPostTarget;
|
||||
import dev.sheldan.abstracto.starboard.model.database.StarboardPost;
|
||||
@@ -90,40 +90,47 @@ public class StarboardServiceBean implements StarboardService {
|
||||
@Autowired
|
||||
private StarboardServiceBean self;
|
||||
|
||||
@Autowired
|
||||
private StarboardPostListenerManager starboardPostListenerManager;
|
||||
|
||||
@Autowired
|
||||
private UserService userService;
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> createStarboardPost(CachedMessage message, List<AUserInAServer> userExceptAuthor, AUserInAServer userReacting, AUserInAServer starredUser) {
|
||||
Long starredUserId = starredUser.getUserInServerId();
|
||||
List<Long> userExceptAuthorIds = userExceptAuthor.stream().map(AUserInAServer::getUserInServerId).collect(Collectors.toList());
|
||||
Long userReactingId = userReacting.getUserReference().getId();
|
||||
return buildStarboardPostModel(message, userExceptAuthor.size()).thenCompose(starboardPostModel ->
|
||||
self.sendStarboardPostAndStore(message, starredUserId, userExceptAuthorIds, starboardPostModel)
|
||||
self.sendStarboardPostAndStore(message, starredUserId, userExceptAuthorIds, starboardPostModel, userReactingId)
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public CompletionStage<Void> sendStarboardPostAndStore(CachedMessage message, Long starredUserId, List<Long> userExceptAuthorIds, StarboardPostModel starboardPostModel) {
|
||||
public CompletionStage<Void> sendStarboardPostAndStore(CachedMessage message, Long starredUserId, List<Long> userExceptAuthorIds, StarboardPostModel starboardPostModel, Long userReactingId) {
|
||||
MessageToSend messageToSend = templateService.renderEmbedTemplate(STARBOARD_POST_TEMPLATE, starboardPostModel);
|
||||
PostTarget starboard = postTargetManagement.getPostTarget(StarboardPostTarget.STARBOARD.getKey(), message.getServerId());
|
||||
List<CompletableFuture<Message>> completableFutures = postTargetService.sendEmbedInPostTarget(messageToSend, StarboardPostTarget.STARBOARD, message.getServerId());
|
||||
Long starboardChannelId = starboard.getChannelReference().getId();
|
||||
return CompletableFuture.allOf(completableFutures.toArray(new CompletableFuture[0])).thenAccept(aVoid ->
|
||||
self.persistPost(message, userExceptAuthorIds, completableFutures, starboardChannelId, starredUserId)
|
||||
self.persistPost(message, userExceptAuthorIds, completableFutures, starboardChannelId, starredUserId, userReactingId)
|
||||
);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void persistPost(CachedMessage message, List<Long> userExceptAuthorIds, List<CompletableFuture<Message>> completableFutures, Long starboardChannelId, Long starredUserId) {
|
||||
public void persistPost(CachedMessage message, List<Long> userExceptAuthorIds, List<CompletableFuture<Message>> completableFutures, Long starboardChannelId, Long starredUserId, Long userReactingId) {
|
||||
AUserInAServer innerStarredUser = userInServerManagementService.loadUserOptional(starredUserId).orElseThrow(() -> new UserInServerNotFoundException(starredUserId));
|
||||
AChannel starboardChannel = channelManagementService.loadChannel(starboardChannelId);
|
||||
Message message1 = completableFutures.get(0).join();
|
||||
Message starboardMessage = completableFutures.get(0).join();
|
||||
AServerAChannelMessage aServerAChannelMessage = AServerAChannelMessage
|
||||
.builder()
|
||||
.messageId(message1.getIdLong())
|
||||
.messageId(starboardMessage.getIdLong())
|
||||
.channel(starboardChannel)
|
||||
.server(starboardChannel.getServer())
|
||||
.build();
|
||||
StarboardPost starboardPost = starboardPostManagementService.createStarboardPost(message, innerStarredUser, aServerAChannelMessage);
|
||||
log.info("Persisting starboard post in channel {} with message {} with {} reactors.", message1.getId(),starboardChannelId, userExceptAuthorIds.size());
|
||||
log.info("Persisting starboard post in channel {} with message {} with {} reactors.", starboardMessage.getId(),starboardChannelId, userExceptAuthorIds.size());
|
||||
if(userExceptAuthorIds.isEmpty()) {
|
||||
log.warn("There are no user ids except the author for the reactions in post {} in guild {} for message {} in channel {}.", starboardPost.getId(), message.getChannelId(), message.getMessageId(), message.getChannelId());
|
||||
}
|
||||
@@ -131,25 +138,23 @@ public class StarboardServiceBean implements StarboardService {
|
||||
AUserInAServer user = userInServerManagementService.loadUserOptional(aLong).orElseThrow(() -> new UserInServerNotFoundException(aLong));
|
||||
starboardPostReactorManagementService.addReactor(starboardPost, user);
|
||||
});
|
||||
starboardPostListenerManager.sendStarboardPostCreatedEvent(userReactingId, starboardPost);
|
||||
}
|
||||
|
||||
|
||||
private CompletableFuture<StarboardPostModel> buildStarboardPostModel(CachedMessage message, Integer starCount) {
|
||||
return memberService.getMemberInServerAsync(message.getServerId(), message.getAuthor().getAuthorId()).thenApply(member -> {
|
||||
return userService.retrieveUserForId(message.getAuthor().getAuthorId()).thenApply(user -> {
|
||||
Optional<TextChannel> channel = channelService.getTextChannelFromServerOptional(message.getServerId(), message.getChannelId());
|
||||
Optional<Guild> guild = guildService.getGuildByIdOptional(message.getServerId());
|
||||
// TODO use model objects instead of building entity models
|
||||
AChannel aChannel = AChannel.builder().id(message.getChannelId()).build();
|
||||
AUser user = AUser.builder().id(message.getAuthor().getAuthorId()).build();
|
||||
String starLevelEmote = getAppropriateEmote(message.getServerId(), starCount);
|
||||
return StarboardPostModel
|
||||
.builder()
|
||||
.message(message)
|
||||
.author(member)
|
||||
.author(user)
|
||||
.sourceChannelId(message.getChannelId())
|
||||
.channel(channel.orElse(null))
|
||||
.aChannel(aChannel)
|
||||
.starCount(starCount)
|
||||
.guild(guild.orElse(null))
|
||||
.user(user)
|
||||
.starLevelEmote(starLevelEmote)
|
||||
.build();
|
||||
});
|
||||
@@ -241,6 +246,13 @@ public class StarboardServiceBean implements StarboardService {
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteStarboardPost(StarboardPost starboardPost, ServerUser userReacting) {
|
||||
deleteStarboardMessagePost(starboardPost);
|
||||
starboardPostManagementService.removePost(starboardPost);
|
||||
starboardPostListenerManager.sendStarboardPostDeletedEvent(starboardPost, userReacting);
|
||||
}
|
||||
|
||||
private String getStarboardRankingEmote(Long serverId, Integer position) {
|
||||
return emoteService.getUsableEmoteOrDefault(serverId, buildBadgeName(position));
|
||||
}
|
||||
|
||||
@@ -12,10 +12,7 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.*;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
@@ -36,6 +33,7 @@ public class StarboardPostManagementServiceBean implements StarboardPostManageme
|
||||
.postMessageId(starredMessage.getMessageId())
|
||||
.sourceChannel(build)
|
||||
.ignored(false)
|
||||
.reactions(new ArrayList<>())
|
||||
.server(starboardPost.getServer())
|
||||
.starboardMessageId(starboardPost.getMessageId())
|
||||
.starboardChannel(starboardPost.getChannel())
|
||||
@@ -45,8 +43,7 @@ public class StarboardPostManagementServiceBean implements StarboardPostManageme
|
||||
starredMessage.getMessageId(), starredMessage.getChannelId(), starredMessage.getServerId(),
|
||||
starboardPost.getMessageId(), starboardPost.getChannel().getId(), starboardPost.getServer().getId(),
|
||||
starredUser.getUserReference().getId());
|
||||
repository.save(post);
|
||||
return post;
|
||||
return repository.save(post);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -57,7 +54,6 @@ public class StarboardPostManagementServiceBean implements StarboardPostManageme
|
||||
@Override
|
||||
public void setStarboardPostMessageId(StarboardPost post, Long messageId) {
|
||||
post.setStarboardMessageId(messageId);
|
||||
repository.save(post);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -33,8 +33,7 @@ public class StarboardPostReactorManagementServiceBean implements StarboardPostR
|
||||
.server(user.getServerReference())
|
||||
.build();
|
||||
log.info("Persisting the reactor {} for starboard post {} in server {}.", user.getUserReference().getId(), post.getId(), user.getServerReference().getId());
|
||||
repository.save(reactor);
|
||||
return reactor;
|
||||
return repository.save(reactor);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -3,10 +3,10 @@ package dev.sheldan.abstracto.starboard.listener;
|
||||
import dev.sheldan.abstracto.core.metric.service.MetricService;
|
||||
import dev.sheldan.abstracto.core.models.ServerUser;
|
||||
import dev.sheldan.abstracto.core.models.cache.CachedAuthor;
|
||||
import dev.sheldan.abstracto.core.models.cache.CachedEmote;
|
||||
import dev.sheldan.abstracto.core.models.cache.CachedMessage;
|
||||
import dev.sheldan.abstracto.core.models.cache.CachedReactions;
|
||||
import dev.sheldan.abstracto.core.models.database.*;
|
||||
import dev.sheldan.abstracto.core.models.listener.ReactionAddedModel;
|
||||
import dev.sheldan.abstracto.core.service.EmoteService;
|
||||
import dev.sheldan.abstracto.core.service.management.ConfigManagementService;
|
||||
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
|
||||
@@ -15,6 +15,7 @@ import dev.sheldan.abstracto.starboard.model.database.StarboardPost;
|
||||
import dev.sheldan.abstracto.starboard.service.StarboardService;
|
||||
import dev.sheldan.abstracto.starboard.service.management.StarboardPostManagementService;
|
||||
import dev.sheldan.abstracto.starboard.service.management.StarboardPostReactorManagementService;
|
||||
import net.dv8tion.jda.api.entities.MessageReaction;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.InjectMocks;
|
||||
@@ -22,18 +23,16 @@ import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class StarboardListenerTest {
|
||||
public class StarAddedListenerTest {
|
||||
|
||||
@InjectMocks
|
||||
private StarboardListener testUnit;
|
||||
private StarAddedListener testUnit;
|
||||
|
||||
@Mock
|
||||
private ConfigManagementService configManagementService;
|
||||
@@ -57,7 +56,10 @@ public class StarboardListenerTest {
|
||||
private MetricService metricService;
|
||||
|
||||
@Mock
|
||||
private CachedReactions cachedReaction;
|
||||
private MessageReaction reaction;
|
||||
|
||||
@Mock
|
||||
private CachedReactions cachedReactions;
|
||||
|
||||
@Mock
|
||||
private CachedMessage cachedMessage;
|
||||
@@ -87,11 +89,14 @@ public class StarboardListenerTest {
|
||||
private StarboardPost post;
|
||||
|
||||
@Mock
|
||||
private CachedEmote cachedEmote;
|
||||
private MessageReaction.ReactionEmote reactionEmote;
|
||||
|
||||
@Mock
|
||||
private AEmote starEmote;
|
||||
|
||||
@Mock
|
||||
private ReactionAddedModel model;
|
||||
|
||||
private static final Long MESSAGE_ID = 5L;
|
||||
private static final Long SERVER_ID = 6L;
|
||||
private static final Long AUTHOR_ID = 4L;
|
||||
@@ -102,7 +107,9 @@ public class StarboardListenerTest {
|
||||
when(cachedAuthor.getAuthorId()).thenReturn(AUTHOR_ID);
|
||||
when(cachedMessage.getAuthor()).thenReturn(cachedAuthor);
|
||||
when(serverUserActing.getUserId()).thenReturn(AUTHOR_ID);
|
||||
testUnit.executeReactionAdded(cachedMessage, cachedReaction, serverUserActing);
|
||||
when(model.getMessage()).thenReturn(cachedMessage);
|
||||
when(model.getUserReacting()).thenReturn(serverUserActing);
|
||||
testUnit.execute(model);
|
||||
verify(emoteService, times(0)).getEmoteOrDefaultEmote(StarboardFeature.STAR_EMOTE, SERVER_ID);
|
||||
}
|
||||
|
||||
@@ -110,9 +117,13 @@ public class StarboardListenerTest {
|
||||
public void testAddingWrongEmote() {
|
||||
when(serverUserActing.getUserId()).thenReturn(USER_ACTING_ID);
|
||||
setupWrongEmote(SERVER_ID, AUTHOR_ID, starEmote);
|
||||
when(cachedReaction.getEmote()).thenReturn(cachedEmote);
|
||||
when(emoteService.compareCachedEmoteWithAEmote(cachedEmote, starEmote)).thenReturn(false);
|
||||
testUnit.executeReactionAdded(cachedMessage, cachedReaction, serverUserActing);
|
||||
when(emoteService.isReactionEmoteAEmote(reactionEmote, starEmote)).thenReturn(false);
|
||||
when(model.getMessage()).thenReturn(cachedMessage);
|
||||
when(model.getUserReacting()).thenReturn(serverUserActing);
|
||||
when(model.getServerId()).thenReturn(SERVER_ID);
|
||||
when(model.getReaction()).thenReturn(reaction);
|
||||
when(reaction.getReactionEmote()).thenReturn(reactionEmote);
|
||||
testUnit.execute(model);
|
||||
verify(emoteService, times(1)).getEmoteOrDefaultEmote(StarboardFeature.STAR_EMOTE, SERVER_ID);
|
||||
verify(emoteService, times(0)).getReactionFromMessageByEmote(any(CachedMessage.class), eq(starEmote));
|
||||
}
|
||||
@@ -122,8 +133,7 @@ public class StarboardListenerTest {
|
||||
Long requiredStars = 5L;
|
||||
setupActingAndAuthor();
|
||||
executeAddingTest(requiredStars, post);
|
||||
verify(starboardService, times(1)).deleteStarboardMessagePost(post);
|
||||
verify(starboardPostManagementService, times(1)).removePost(post);
|
||||
verify(starboardService, times(1)).deleteStarboardPost(post, serverUserActing);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -154,67 +164,6 @@ public class StarboardListenerTest {
|
||||
verify(starboardPostReactorManagementService, times(1)).addReactor(post, userInServerActing);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAuthorRemovingReaction() {
|
||||
when(cachedAuthor.getAuthorId()).thenReturn(AUTHOR_ID);
|
||||
when(cachedMessage.getAuthor()).thenReturn(cachedAuthor);
|
||||
when(serverUserActing.getUserId()).thenReturn(AUTHOR_ID);
|
||||
testUnit.executeReactionRemoved(cachedMessage, cachedReaction, serverUserActing);
|
||||
verify(emoteService, times(0)).getEmoteOrDefaultEmote(StarboardFeature.STAR_EMOTE, SERVER_ID);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemovingWrongEmote() {
|
||||
when(serverUserActing.getUserId()).thenReturn(USER_ACTING_ID);
|
||||
setupWrongEmote(SERVER_ID, AUTHOR_ID, starEmote);
|
||||
testUnit.executeReactionRemoved(cachedMessage, cachedReaction, serverUserActing);
|
||||
verify(emoteService, times(1)).getEmoteOrDefaultEmote(StarboardFeature.STAR_EMOTE, SERVER_ID);
|
||||
verify(emoteService, times(0)).getReactionFromMessageByEmote(any(CachedMessage.class), eq(starEmote));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemoveReactionFromExistingPostBelowThreshold() {
|
||||
Long requiredStars = 5L;
|
||||
List<ServerUser> remainingUsers = Arrays.asList(serverUserActing);
|
||||
setupActingAndAuthor();
|
||||
executeRemovalTest(requiredStars, remainingUsers);
|
||||
verify(starboardService, times(1)).deleteStarboardMessagePost(eq(post));
|
||||
verify(starboardPostManagementService, times(1)).removePost(eq(post));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemoveReactionFromExistingPostAboveThreshold() {
|
||||
Long requiredStars = 0L;
|
||||
List<ServerUser> remainingUsers = Arrays.asList(serverUserActing);
|
||||
setupActingAndAuthor();
|
||||
when(userInServerManagementService.loadOrCreateUser(serverUserActing)).thenReturn(userInServerActing);
|
||||
executeRemovalTest(requiredStars, remainingUsers);
|
||||
verify(metricService, times(1)).incrementCounter(any());
|
||||
verify(starboardService, times(0)).deleteStarboardMessagePost(eq(post));
|
||||
verify(starboardPostManagementService, times(0)).removePost(eq(post));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemoveReactionFromExistingPostTriggeringThreshold() {
|
||||
Long requiredStars = 1L;
|
||||
ArrayList<ServerUser> usersRemaining = new ArrayList<>();
|
||||
setupActingAndAuthor();
|
||||
executeRemovalTest(requiredStars, usersRemaining);
|
||||
verify(metricService, times(2)).incrementCounter(any());
|
||||
verify(starboardService, times(1)).deleteStarboardMessagePost(eq(post));
|
||||
verify(starboardPostManagementService, times(1)).removePost(eq(post));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReactionsClearedOnStarredMessage() {
|
||||
executeClearingTest(Mockito.mock(StarboardPost.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReactionsClearedOnNotStarredMessage() {
|
||||
executeClearingTest(null);
|
||||
}
|
||||
|
||||
private void setupActingAndAuthor() {
|
||||
when(userInServerActing.getUserReference()).thenReturn(userActing);
|
||||
when(userActing.getId()).thenReturn(USER_ACTING_ID);
|
||||
@@ -224,57 +173,16 @@ public class StarboardListenerTest {
|
||||
when(aUser.getId()).thenReturn(AUTHOR_ID);
|
||||
}
|
||||
|
||||
|
||||
private void executeClearingTest(StarboardPost post) {
|
||||
when(cachedMessage.getMessageId()).thenReturn(MESSAGE_ID);
|
||||
when(starboardPostManagementService.findByMessageId(MESSAGE_ID)).thenReturn(Optional.ofNullable(post));
|
||||
testUnit.executeReactionCleared(cachedMessage);
|
||||
int callCount = post != null ? 1 : 0;
|
||||
verify(starboardPostReactorManagementService, times(callCount)).removeReactors(post);
|
||||
verify(starboardService, times(callCount)).deleteStarboardMessagePost(eq(post));
|
||||
verify(starboardPostManagementService, times(callCount)).removePost(eq(post));
|
||||
}
|
||||
|
||||
|
||||
private void executeRemovalTest(Long requiredStars, List<ServerUser> remainingUsers) {
|
||||
when(cachedMessage.getServerId()).thenReturn(SERVER_ID);
|
||||
when(cachedMessage.getMessageId()).thenReturn(MESSAGE_ID);
|
||||
when(cachedAuthor.getAuthorId()).thenReturn(AUTHOR_ID);
|
||||
when(cachedMessage.getAuthor()).thenReturn(cachedAuthor);
|
||||
when(cachedReaction.getEmote()).thenReturn(cachedEmote);
|
||||
when(emoteService.compareCachedEmoteWithAEmote(cachedEmote, starEmote)).thenReturn(true);
|
||||
when(emoteService.getEmoteOrDefaultEmote(StarboardFeature.STAR_EMOTE, SERVER_ID)).thenReturn(starEmote);
|
||||
CachedReactions reaction = Mockito.mock(CachedReactions.class);
|
||||
when(reaction.getUsers()).thenReturn(remainingUsers);
|
||||
when(emoteService.getReactionFromMessageByEmote(cachedMessage, starEmote)).thenReturn(Optional.of(reaction));
|
||||
when(starboardPostManagementService.findByMessageId(MESSAGE_ID)).thenReturn(Optional.ofNullable(post));
|
||||
when(userInServerManagementService.loadOrCreateUser(SERVER_ID, AUTHOR_ID)).thenReturn(userInAServer);
|
||||
when(serverUserActing.getUserId()).thenReturn(USER_ACTING_ID);
|
||||
when(serverUserActing.getServerId()).thenReturn(SERVER_ID);
|
||||
if(!remainingUsers.isEmpty()) {
|
||||
when(userInServerManagementService.loadUserOptional(SERVER_ID, USER_ACTING_ID)).thenReturn(Optional.of(userInServerActing));
|
||||
}
|
||||
AConfig starRequirementConfig = Mockito.mock(AConfig.class);
|
||||
when(starRequirementConfig.getLongValue()).thenReturn(requiredStars);
|
||||
when(configManagementService.loadConfig(SERVER_ID, StarboardListener.FIRST_LEVEL_THRESHOLD_KEY)).thenReturn(starRequirementConfig);
|
||||
testUnit.executeReactionRemoved(cachedMessage, cachedReaction, serverUserActing);
|
||||
verify(emoteService, times(1)).getEmoteOrDefaultEmote(StarboardFeature.STAR_EMOTE, SERVER_ID);
|
||||
verify(emoteService, times(1)).getReactionFromMessageByEmote(cachedMessage, starEmote);
|
||||
}
|
||||
|
||||
private void executeAddingTest(Long requiredStars, StarboardPost postToUse) {
|
||||
when(cachedMessage.getServerId()).thenReturn(SERVER_ID);
|
||||
when(cachedMessage.getMessageId()).thenReturn(MESSAGE_ID);
|
||||
when(cachedAuthor.getAuthorId()).thenReturn(AUTHOR_ID);
|
||||
when(cachedMessage.getAuthor()).thenReturn(cachedAuthor);
|
||||
when(cachedReaction.getEmote()).thenReturn(cachedEmote);
|
||||
when(emoteService.compareCachedEmoteWithAEmote(cachedEmote, starEmote)).thenReturn(true);
|
||||
when(reaction.getReactionEmote()).thenReturn(reactionEmote);
|
||||
when(emoteService.isReactionEmoteAEmote(reactionEmote, starEmote)).thenReturn(true);
|
||||
when(emoteService.getEmoteOrDefaultEmote(StarboardFeature.STAR_EMOTE, SERVER_ID)).thenReturn(starEmote);
|
||||
CachedReactions reaction = Mockito.mock(CachedReactions.class);
|
||||
when(serverUserActing.getUserId()).thenReturn(USER_ACTING_ID);
|
||||
when(serverUserActing.getServerId()).thenReturn(SERVER_ID);
|
||||
when(reaction.getUsers()).thenReturn(Arrays.asList(serverUserActing));
|
||||
when(emoteService.getReactionFromMessageByEmote(cachedMessage, starEmote)).thenReturn(Optional.of(reaction));
|
||||
when(starboardPostManagementService.findByMessageId(MESSAGE_ID)).thenReturn(Optional.ofNullable(postToUse));
|
||||
when(userInServerManagementService.loadOrCreateUser(SERVER_ID, AUTHOR_ID)).thenReturn(userInAServer);
|
||||
when(userInServerManagementService.loadOrCreateUser(serverUserActing)).thenReturn(userInServerActing);
|
||||
@@ -282,16 +190,21 @@ public class StarboardListenerTest {
|
||||
AConfig starRequirementConfig = Mockito.mock(AConfig.class);
|
||||
when(starRequirementConfig.getLongValue()).thenReturn(requiredStars);
|
||||
when(configManagementService.loadConfig(SERVER_ID, StarboardListener.FIRST_LEVEL_THRESHOLD_KEY)).thenReturn(starRequirementConfig);
|
||||
testUnit.executeReactionAdded(cachedMessage, cachedReaction, serverUserActing);
|
||||
when(model.getMessage()).thenReturn(cachedMessage);
|
||||
when(cachedReactions.getUsers()).thenReturn(Arrays.asList(serverUserActing));
|
||||
when(emoteService.getReactionFromMessageByEmote(cachedMessage, starEmote)).thenReturn(Optional.of(cachedReactions));
|
||||
when(model.getUserReacting()).thenReturn(serverUserActing);
|
||||
when(model.getReaction()).thenReturn(reaction);
|
||||
when(model.getServerId()).thenReturn(SERVER_ID);
|
||||
testUnit.execute(model);
|
||||
verify(emoteService, times(1)).getEmoteOrDefaultEmote(StarboardFeature.STAR_EMOTE, SERVER_ID);
|
||||
verify(emoteService, times(1)).getReactionFromMessageByEmote(cachedMessage, starEmote);
|
||||
}
|
||||
|
||||
private void setupWrongEmote(Long serverId, Long authorId, AEmote starEmote) {
|
||||
when(cachedMessage.getServerId()).thenReturn(serverId);
|
||||
when(cachedAuthor.getAuthorId()).thenReturn(authorId);
|
||||
when(cachedMessage.getAuthor()).thenReturn(cachedAuthor);
|
||||
when(cachedReaction.getEmote()).thenReturn(cachedEmote);
|
||||
when(reaction.getReactionEmote()).thenReturn(reactionEmote);
|
||||
when(emoteService.getEmoteOrDefaultEmote(StarboardFeature.STAR_EMOTE, serverId)).thenReturn(starEmote);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package dev.sheldan.abstracto.starboard.listener;
|
||||
|
||||
import dev.sheldan.abstracto.core.metric.service.MetricService;
|
||||
import dev.sheldan.abstracto.core.models.cache.CachedMessage;
|
||||
import dev.sheldan.abstracto.core.models.listener.ReactionClearedModel;
|
||||
import dev.sheldan.abstracto.starboard.model.database.StarboardPost;
|
||||
import dev.sheldan.abstracto.starboard.service.StarboardService;
|
||||
import dev.sheldan.abstracto.starboard.service.management.StarboardPostManagementService;
|
||||
import dev.sheldan.abstracto.starboard.service.management.StarboardPostReactorManagementService;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class StarClearedListenerTest {
|
||||
|
||||
@InjectMocks
|
||||
private StarClearedListener testUnit;
|
||||
|
||||
@Mock
|
||||
private StarboardService starboardService;
|
||||
|
||||
@Mock
|
||||
private StarboardPostManagementService starboardPostManagementService;
|
||||
|
||||
@Mock
|
||||
private StarboardPostReactorManagementService starboardPostReactorManagementService;
|
||||
|
||||
@Mock
|
||||
private MetricService metricService;
|
||||
|
||||
@Mock
|
||||
private CachedMessage cachedMessage;
|
||||
|
||||
@Mock
|
||||
private ReactionClearedModel model;
|
||||
|
||||
private static final Long MESSAGE_ID = 5L;
|
||||
|
||||
@Test
|
||||
public void testReactionsClearedOnStarredMessage() {
|
||||
executeClearingTest(Mockito.mock(StarboardPost.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReactionsClearedOnNotStarredMessage() {
|
||||
executeClearingTest(null);
|
||||
}
|
||||
|
||||
private void executeClearingTest(StarboardPost post) {
|
||||
when(cachedMessage.getMessageId()).thenReturn(MESSAGE_ID);
|
||||
when(model.getMessage()).thenReturn(cachedMessage);
|
||||
when(starboardPostManagementService.findByMessageId(MESSAGE_ID)).thenReturn(Optional.ofNullable(post));
|
||||
testUnit.execute(model);
|
||||
int callCount = post != null ? 1 : 0;
|
||||
verify(starboardPostReactorManagementService, times(callCount)).removeReactors(post);
|
||||
verify(starboardService, times(callCount)).deleteStarboardPost(post, null);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,210 @@
|
||||
package dev.sheldan.abstracto.starboard.listener;
|
||||
|
||||
import dev.sheldan.abstracto.core.metric.service.MetricService;
|
||||
import dev.sheldan.abstracto.core.models.ServerUser;
|
||||
import dev.sheldan.abstracto.core.models.cache.CachedAuthor;
|
||||
import dev.sheldan.abstracto.core.models.cache.CachedMessage;
|
||||
import dev.sheldan.abstracto.core.models.cache.CachedReactions;
|
||||
import dev.sheldan.abstracto.core.models.database.*;
|
||||
import dev.sheldan.abstracto.core.models.listener.ReactionRemovedModel;
|
||||
import dev.sheldan.abstracto.core.service.EmoteService;
|
||||
import dev.sheldan.abstracto.core.service.management.ConfigManagementService;
|
||||
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
|
||||
import dev.sheldan.abstracto.starboard.config.StarboardFeature;
|
||||
import dev.sheldan.abstracto.starboard.model.database.StarboardPost;
|
||||
import dev.sheldan.abstracto.starboard.service.StarboardService;
|
||||
import dev.sheldan.abstracto.starboard.service.management.StarboardPostManagementService;
|
||||
import dev.sheldan.abstracto.starboard.service.management.StarboardPostReactorManagementService;
|
||||
import net.dv8tion.jda.api.entities.MessageReaction;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class StarRemovedListenerTest {
|
||||
|
||||
@InjectMocks
|
||||
private StarRemovedListener testUnit;
|
||||
|
||||
@Mock
|
||||
private ConfigManagementService configManagementService;
|
||||
|
||||
@Mock
|
||||
private StarboardService starboardService;
|
||||
|
||||
@Mock
|
||||
private StarboardPostManagementService starboardPostManagementService;
|
||||
|
||||
@Mock
|
||||
private StarboardPostReactorManagementService starboardPostReactorManagementService;
|
||||
|
||||
@Mock
|
||||
private UserInServerManagementService userInServerManagementService;
|
||||
|
||||
@Mock
|
||||
private EmoteService emoteService;
|
||||
|
||||
@Mock
|
||||
private MetricService metricService;
|
||||
|
||||
@Mock
|
||||
private MessageReaction reaction;
|
||||
|
||||
@Mock
|
||||
private CachedMessage cachedMessage;
|
||||
|
||||
@Mock
|
||||
private ServerUser serverUserActing;
|
||||
|
||||
@Mock
|
||||
private CachedAuthor cachedAuthor;
|
||||
|
||||
@Mock
|
||||
private AUserInAServer userInServerActing;
|
||||
|
||||
@Mock
|
||||
private AUser userActing;
|
||||
|
||||
@Mock
|
||||
private CachedReactions cachedReactions;
|
||||
|
||||
@Mock
|
||||
private AUserInAServer userInAServer;
|
||||
|
||||
@Mock
|
||||
private AUser aUser;
|
||||
|
||||
@Mock
|
||||
private AServer server;
|
||||
|
||||
@Mock
|
||||
private StarboardPost post;
|
||||
|
||||
@Mock
|
||||
private MessageReaction.ReactionEmote reactionEmote;
|
||||
|
||||
@Mock
|
||||
private AEmote starEmote;
|
||||
|
||||
@Mock
|
||||
private ReactionRemovedModel model;
|
||||
|
||||
private static final Long MESSAGE_ID = 5L;
|
||||
private static final Long SERVER_ID = 6L;
|
||||
private static final Long AUTHOR_ID = 4L;
|
||||
private static final Long USER_ACTING_ID = 7L;
|
||||
|
||||
@Test
|
||||
public void testAuthorRemovingReaction() {
|
||||
when(cachedAuthor.getAuthorId()).thenReturn(AUTHOR_ID);
|
||||
when(cachedMessage.getAuthor()).thenReturn(cachedAuthor);
|
||||
when(serverUserActing.getUserId()).thenReturn(AUTHOR_ID);
|
||||
when(model.getMessage()).thenReturn(cachedMessage);
|
||||
when(model.getUserRemoving()).thenReturn(serverUserActing);
|
||||
testUnit.execute(model);
|
||||
verify(emoteService, times(0)).getEmoteOrDefaultEmote(StarboardFeature.STAR_EMOTE, SERVER_ID);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemovingWrongEmote() {
|
||||
when(serverUserActing.getUserId()).thenReturn(USER_ACTING_ID);
|
||||
setupWrongEmote(SERVER_ID, AUTHOR_ID, starEmote);
|
||||
when(model.getMessage()).thenReturn(cachedMessage);
|
||||
when(model.getUserRemoving()).thenReturn(serverUserActing);
|
||||
when(model.getReaction()).thenReturn(reaction);
|
||||
when(reaction.getReactionEmote()).thenReturn(reactionEmote);
|
||||
when(model.getServerId()).thenReturn(SERVER_ID);
|
||||
testUnit.execute(model);
|
||||
verify(emoteService, times(1)).getEmoteOrDefaultEmote(StarboardFeature.STAR_EMOTE, SERVER_ID);
|
||||
verify(emoteService, times(0)).getReactionFromMessageByEmote(any(CachedMessage.class), eq(starEmote));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemoveReactionFromExistingPostBelowThreshold() {
|
||||
Long requiredStars = 5L;
|
||||
List<ServerUser> remainingUsers = Arrays.asList(serverUserActing);
|
||||
setupActingAndAuthor();
|
||||
executeRemovalTest(requiredStars, remainingUsers);
|
||||
verify(starboardService, times(1)).deleteStarboardPost(post, serverUserActing);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemoveReactionFromExistingPostAboveThreshold() {
|
||||
Long requiredStars = 0L;
|
||||
List<ServerUser> remainingUsers = Arrays.asList(serverUserActing);
|
||||
setupActingAndAuthor();
|
||||
when(userInServerManagementService.loadOrCreateUser(serverUserActing)).thenReturn(userInServerActing);
|
||||
executeRemovalTest(requiredStars, remainingUsers);
|
||||
verify(metricService, times(1)).incrementCounter(any());
|
||||
verify(starboardService, times(0)).deleteStarboardMessagePost(eq(post));
|
||||
verify(starboardPostManagementService, times(0)).removePost(eq(post));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemoveReactionFromExistingPostTriggeringThreshold() {
|
||||
Long requiredStars = 1L;
|
||||
ArrayList<ServerUser> usersRemaining = new ArrayList<>();
|
||||
setupActingAndAuthor();
|
||||
executeRemovalTest(requiredStars, usersRemaining);
|
||||
verify(metricService, times(2)).incrementCounter(any());
|
||||
verify(starboardService, times(1)).deleteStarboardPost(post, serverUserActing);
|
||||
}
|
||||
|
||||
private void setupActingAndAuthor() {
|
||||
when(userInServerActing.getUserReference()).thenReturn(userActing);
|
||||
when(userActing.getId()).thenReturn(USER_ACTING_ID);
|
||||
when(userInAServer.getServerReference()).thenReturn(server);
|
||||
when(server.getId()).thenReturn(SERVER_ID);
|
||||
when(userInAServer.getUserReference()).thenReturn(aUser);
|
||||
when(aUser.getId()).thenReturn(AUTHOR_ID);
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void executeRemovalTest(Long requiredStars, List<ServerUser> remainingUsers) {
|
||||
when(cachedMessage.getServerId()).thenReturn(SERVER_ID);
|
||||
when(cachedMessage.getMessageId()).thenReturn(MESSAGE_ID);
|
||||
when(cachedAuthor.getAuthorId()).thenReturn(AUTHOR_ID);
|
||||
when(cachedMessage.getAuthor()).thenReturn(cachedAuthor);
|
||||
when(reaction.getReactionEmote()).thenReturn(reactionEmote);
|
||||
when(emoteService.isReactionEmoteAEmote(reactionEmote, starEmote)).thenReturn(true);
|
||||
when(emoteService.getEmoteOrDefaultEmote(StarboardFeature.STAR_EMOTE, SERVER_ID)).thenReturn(starEmote);
|
||||
when(cachedReactions.getUsers()).thenReturn(remainingUsers);
|
||||
when(emoteService.getReactionFromMessageByEmote(cachedMessage, starEmote)).thenReturn(Optional.of(cachedReactions));
|
||||
when(starboardPostManagementService.findByMessageId(MESSAGE_ID)).thenReturn(Optional.ofNullable(post));
|
||||
when(userInServerManagementService.loadOrCreateUser(SERVER_ID, AUTHOR_ID)).thenReturn(userInAServer);
|
||||
when(serverUserActing.getUserId()).thenReturn(USER_ACTING_ID);
|
||||
when(serverUserActing.getServerId()).thenReturn(SERVER_ID);
|
||||
if(!remainingUsers.isEmpty()) {
|
||||
when(userInServerManagementService.loadUserOptional(SERVER_ID, USER_ACTING_ID)).thenReturn(Optional.of(userInServerActing));
|
||||
}
|
||||
AConfig starRequirementConfig = Mockito.mock(AConfig.class);
|
||||
when(starRequirementConfig.getLongValue()).thenReturn(requiredStars);
|
||||
when(configManagementService.loadConfig(SERVER_ID, StarboardListener.FIRST_LEVEL_THRESHOLD_KEY)).thenReturn(starRequirementConfig);
|
||||
when(model.getMessage()).thenReturn(cachedMessage);
|
||||
when(model.getUserRemoving()).thenReturn(serverUserActing);
|
||||
when(model.getReaction()).thenReturn(reaction);
|
||||
when(model.getServerId()).thenReturn(SERVER_ID);
|
||||
testUnit.execute(model);
|
||||
verify(emoteService, times(1)).getEmoteOrDefaultEmote(StarboardFeature.STAR_EMOTE, SERVER_ID);
|
||||
verify(emoteService, times(1)).getReactionFromMessageByEmote(cachedMessage, starEmote);
|
||||
}
|
||||
|
||||
|
||||
private void setupWrongEmote(Long serverId, Long authorId, AEmote starEmote) {
|
||||
when(cachedAuthor.getAuthorId()).thenReturn(authorId);
|
||||
when(cachedMessage.getAuthor()).thenReturn(cachedAuthor);
|
||||
when(reaction.getReactionEmote()).thenReturn(reactionEmote);
|
||||
when(emoteService.getEmoteOrDefaultEmote(StarboardFeature.STAR_EMOTE, serverId)).thenReturn(starEmote);
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@ package dev.sheldan.abstracto.starboard.listener;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.cache.CachedMessage;
|
||||
import dev.sheldan.abstracto.core.models.database.AChannel;
|
||||
import dev.sheldan.abstracto.core.models.listener.MessageDeletedModel;
|
||||
import dev.sheldan.abstracto.starboard.model.database.StarboardPost;
|
||||
import dev.sheldan.abstracto.starboard.service.management.StarboardPostManagementService;
|
||||
import org.junit.Test;
|
||||
@@ -28,9 +29,11 @@ public class StarboardPostDeletedListenerTest {
|
||||
public void deleteNonStarboardPost() {
|
||||
Long messageId = 4L;
|
||||
when(starboardPostManagementService.findByStarboardPostId(messageId)).thenReturn(Optional.empty());
|
||||
MessageDeletedModel model = Mockito.mock(MessageDeletedModel.class);
|
||||
CachedMessage cachedMessage = Mockito.mock(CachedMessage.class);
|
||||
when(cachedMessage.getMessageId()).thenReturn(messageId);
|
||||
testUnit.execute(cachedMessage);
|
||||
when(model.getCachedMessage()).thenReturn(cachedMessage);
|
||||
testUnit.execute(model);
|
||||
verify( starboardPostManagementService, times(0)).setStarboardPostIgnored(messageId, true);
|
||||
}
|
||||
|
||||
@@ -47,7 +50,9 @@ public class StarboardPostDeletedListenerTest {
|
||||
CachedMessage cachedMessage = Mockito.mock(CachedMessage.class);
|
||||
when(cachedMessage.getServerId()).thenReturn(serverId);
|
||||
when(cachedMessage.getMessageId()).thenReturn(messageId);
|
||||
testUnit.execute(cachedMessage);
|
||||
MessageDeletedModel model = Mockito.mock(MessageDeletedModel.class);
|
||||
when(model.getCachedMessage()).thenReturn(cachedMessage);
|
||||
testUnit.execute(model);
|
||||
verify( starboardPostManagementService, times(1)).setStarboardPostIgnored(messageId, true);
|
||||
}
|
||||
|
||||
|
||||
@@ -20,15 +20,13 @@ import dev.sheldan.abstracto.starboard.model.database.StarboardPostReaction;
|
||||
import dev.sheldan.abstracto.starboard.model.template.*;
|
||||
import dev.sheldan.abstracto.starboard.service.management.StarboardPostManagementService;
|
||||
import dev.sheldan.abstracto.starboard.service.management.StarboardPostReactorManagementService;
|
||||
import net.dv8tion.jda.api.entities.Guild;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
import net.dv8tion.jda.api.entities.TextChannel;
|
||||
import net.dv8tion.jda.api.entities.*;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.*;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
@@ -77,6 +75,12 @@ public class StarboardServiceBeanTest {
|
||||
@Mock
|
||||
private UserInServerManagementService userInServerManagementService;
|
||||
|
||||
@Mock
|
||||
private ApplicationEventPublisher eventPublisher;
|
||||
|
||||
@Mock
|
||||
private UserService userService;
|
||||
|
||||
@Mock
|
||||
private MessageService messageService;
|
||||
|
||||
@@ -95,6 +99,9 @@ public class StarboardServiceBeanTest {
|
||||
@Mock
|
||||
private TextChannel mockedTextChannel;
|
||||
|
||||
@Mock
|
||||
private User starredJdaUser;
|
||||
|
||||
@Mock
|
||||
private Member starredMember;
|
||||
|
||||
@@ -107,6 +114,9 @@ public class StarboardServiceBeanTest {
|
||||
@Mock
|
||||
private AServer server;
|
||||
|
||||
@Mock
|
||||
private AUser aUser;
|
||||
|
||||
private static final Long STARRED_USER_ID = 5L;
|
||||
private static final Long STARRED_SERVER_USER_ID = 2L;
|
||||
private static final Long SERVER_ID = 6L;
|
||||
@@ -116,6 +126,7 @@ public class StarboardServiceBeanTest {
|
||||
private static final Long CHANNEL_ID = 10L;
|
||||
private static final Long MESSAGE_ID = 11L;
|
||||
private static final Long SECOND_MESSAGE_ID = 12L;
|
||||
private static final Long STARRING_USER_ID = 13L;
|
||||
|
||||
@Captor
|
||||
private ArgumentCaptor<AUserInAServer> userInAServerArgumentCaptor;
|
||||
@@ -131,6 +142,8 @@ public class StarboardServiceBeanTest {
|
||||
AUserInAServer secondUserExceptAuthor = Mockito.mock(AUserInAServer.class);
|
||||
userExceptAuthor.add(secondUserExceptAuthor);
|
||||
AUserInAServer userReacting = Mockito.mock(AUserInAServer.class);
|
||||
when(userReacting.getUserReference()).thenReturn(aUser);
|
||||
when(aUser.getId()).thenReturn(STARRING_USER_ID);
|
||||
AUserInAServer starredUser = Mockito.mock(AUserInAServer.class);
|
||||
when(starredUser.getUserInServerId()).thenReturn(STARRED_SERVER_USER_ID);
|
||||
CachedAuthor cachedAuthor = Mockito.mock(CachedAuthor.class);
|
||||
@@ -139,8 +152,7 @@ public class StarboardServiceBeanTest {
|
||||
when(message.getAuthor()).thenReturn(cachedAuthor);
|
||||
when(message.getServerId()).thenReturn(SERVER_ID);
|
||||
when(message.getChannelId()).thenReturn(CHANNEL_ID);
|
||||
Member authorMember = Mockito.mock(Member.class);
|
||||
when(memberService.getMemberInServerAsync(SERVER_ID, STARRED_USER_ID)).thenReturn(CompletableFuture.completedFuture(authorMember));
|
||||
when(userService.retrieveUserForId(STARRED_USER_ID)).thenReturn(CompletableFuture.completedFuture(starredJdaUser));
|
||||
when(channelService.getTextChannelFromServerOptional(SERVER_ID, CHANNEL_ID)).thenReturn(Optional.of(mockedTextChannel));
|
||||
when(guildService.getGuildByIdOptional(SERVER_ID)).thenReturn(Optional.of(guild));
|
||||
SystemConfigProperty config = Mockito.mock(SystemConfigProperty.class);
|
||||
@@ -152,10 +164,11 @@ public class StarboardServiceBeanTest {
|
||||
when(defaultConfigManagementService.getDefaultConfig(StarboardFeature.STAR_LVL_CONFIG_PREFIX + "2")).thenReturn(config);
|
||||
when(defaultConfigManagementService.getDefaultConfig(StarboardFeature.STAR_LVL_CONFIG_PREFIX + "3")).thenReturn(config);
|
||||
when(emoteService.getUsableEmoteOrDefault(SERVER_ID, StarboardFeature.STAR_EMOTE_PREFIX + "2")).thenReturn("b");
|
||||
when(self.sendStarboardPostAndStore(eq(message), eq(STARRED_SERVER_USER_ID), anyList(), any())).thenReturn(CompletableFuture.completedFuture(null));
|
||||
when(self.sendStarboardPostAndStore(eq(message), eq(STARRED_SERVER_USER_ID), anyList(), any(), eq(STARRING_USER_ID))).thenReturn(CompletableFuture.completedFuture(null));
|
||||
CompletableFuture<Void> createPostFuture = testUnit.createStarboardPost(message, userExceptAuthor, userReacting, starredUser);
|
||||
createPostFuture.join();
|
||||
Assert.assertFalse(createPostFuture.isCompletedExceptionally());
|
||||
verify(self, times(1)).sendStarboardPostAndStore(eq(message), eq(STARRED_SERVER_USER_ID), anyList(), any(), eq(STARRING_USER_ID));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -170,8 +183,8 @@ public class StarboardServiceBeanTest {
|
||||
when(postTargetManagement.getPostTarget(StarboardPostTarget.STARBOARD.getKey(), SERVER_ID)).thenReturn(postTarget);
|
||||
when(postTargetService.sendEmbedInPostTarget(messageToSend, StarboardPostTarget.STARBOARD, SERVER_ID)).thenReturn(Arrays.asList(CompletableFuture.completedFuture(null)));
|
||||
ArrayList<Long> userExceptAuthorIds = new ArrayList<>();
|
||||
testUnit.sendStarboardPostAndStore(message, STARRED_USER_ID, userExceptAuthorIds, model);
|
||||
verify(self, times(1)).persistPost(eq(message), eq(userExceptAuthorIds), any(), eq(STARBOARD_CHANNEL_ID), eq(STARRED_USER_ID));
|
||||
testUnit.sendStarboardPostAndStore(message, STARRED_USER_ID, userExceptAuthorIds, model, STARRING_USER_ID);
|
||||
verify(self, times(1)).persistPost(eq(message), eq(userExceptAuthorIds), any(), eq(STARBOARD_CHANNEL_ID), eq(STARRED_USER_ID), eq(STARRING_USER_ID));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -181,9 +194,13 @@ public class StarboardServiceBeanTest {
|
||||
CachedMessage message = Mockito.mock(CachedMessage.class);
|
||||
List<Long> userExceptAuthorIds = Arrays.asList(FIRST_USER_IN_SERVER_ID, SECOND_USER_IN_SERVER_ID);
|
||||
List<CompletableFuture<Message>> futures = Arrays.asList(CompletableFuture.completedFuture(sendPost));
|
||||
when(sendPost.getGuild()).thenReturn(guild);
|
||||
when(sendPost.getChannel()).thenReturn(mockedTextChannel);
|
||||
when(sendPost.getIdLong()).thenReturn(MESSAGE_ID);
|
||||
when(userInServerManagementService.loadUserOptional(STARRED_SERVER_USER_ID)).thenReturn(Optional.of(starredUser));
|
||||
when(userInServerManagementService.loadUserOptional(FIRST_USER_IN_SERVER_ID)).thenReturn(Optional.of(userReacting));
|
||||
when(userReacting.getUserInServerId()).thenReturn(FIRST_USER_IN_SERVER_ID);
|
||||
when(userReacting.getUserReference()).thenReturn(aUser);
|
||||
AChannel channel = Mockito.mock(AChannel.class);
|
||||
when(channelManagementService.loadChannel(CHANNEL_ID)).thenReturn(channel);
|
||||
StarboardPost post = Mockito.mock(StarboardPost.class);
|
||||
@@ -191,7 +208,8 @@ public class StarboardServiceBeanTest {
|
||||
AUserInAServer secondStarrerUserObj = Mockito.mock(AUserInAServer.class);
|
||||
when(userInServerManagementService.loadUserOptional(SECOND_USER_IN_SERVER_ID)).thenReturn(Optional.of(secondStarrerUserObj));
|
||||
when(secondStarrerUserObj.getUserInServerId()).thenReturn(SECOND_USER_IN_SERVER_ID);
|
||||
testUnit.persistPost(message, userExceptAuthorIds, futures, CHANNEL_ID, STARRED_SERVER_USER_ID);
|
||||
when(secondStarrerUserObj.getUserReference()).thenReturn(aUser);
|
||||
testUnit.persistPost(message, userExceptAuthorIds, futures, CHANNEL_ID, STARRED_SERVER_USER_ID, STARRING_USER_ID);
|
||||
verify(starboardPostReactorManagementService, times(2)).addReactor(eq(post), userInAServerArgumentCaptor.capture());
|
||||
List<AUserInAServer> addedReactors = userInAServerArgumentCaptor.getAllValues();
|
||||
Assert.assertEquals(FIRST_USER_IN_SERVER_ID, addedReactors.get(0).getUserInServerId());
|
||||
@@ -225,7 +243,7 @@ public class StarboardServiceBeanTest {
|
||||
when(defaultConfigManagementService.getDefaultConfig(StarboardFeature.STAR_LEVELS_CONFIG_KEY)).thenReturn(config);
|
||||
when(defaultConfigManagementService.getDefaultConfig(StarboardFeature.STAR_LVL_CONFIG_PREFIX + 1)).thenReturn(config);
|
||||
when(starboardPostManagementService.findByStarboardPostId(starboardPostId)).thenReturn(Optional.of(post));
|
||||
when(memberService.getMemberInServerAsync(SERVER_ID, STARRED_USER_ID)).thenReturn(CompletableFuture.completedFuture(starredMember));
|
||||
when(userService.retrieveUserForId(STARRED_USER_ID)).thenReturn(CompletableFuture.completedFuture(starredJdaUser));
|
||||
List<AUserInAServer > userExceptAuthor = new ArrayList<>();
|
||||
CompletableFuture<Void> future = testUnit.updateStarboardPost(post, message, userExceptAuthor);
|
||||
future.join();
|
||||
@@ -254,7 +272,7 @@ public class StarboardServiceBeanTest {
|
||||
CachedMessage message = Mockito.mock(CachedMessage.class);
|
||||
List<Long> userExceptAuthorIds = Arrays.asList(FIRST_USER_IN_SERVER_ID);
|
||||
List<CompletableFuture<Message>> futures = Arrays.asList(CompletableFuture.completedFuture(sendPost));
|
||||
testUnit.persistPost(message, userExceptAuthorIds, futures, CHANNEL_ID, SECOND_USER_IN_SERVER_ID);
|
||||
testUnit.persistPost(message, userExceptAuthorIds, futures, CHANNEL_ID, SECOND_USER_IN_SERVER_ID, STARRING_USER_ID);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
package dev.sheldan.abstracto.starboard.listener;
|
||||
|
||||
public enum StarboardPostState {
|
||||
CREATED, UPDATED, UPDATED_CHANGED_THRESHOLD, DELETED
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package dev.sheldan.abstracto.starboard.listener;
|
||||
|
||||
import dev.sheldan.abstracto.core.listener.DefaultListenerResult;
|
||||
import dev.sheldan.abstracto.core.listener.FeatureAwareListener;
|
||||
import dev.sheldan.abstracto.starboard.model.StarboardPostUpdatedModel;
|
||||
|
||||
public interface StarboardPostUpdatedListener extends FeatureAwareListener<StarboardPostUpdatedModel, DefaultListenerResult> {
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package dev.sheldan.abstracto.starboard.model;
|
||||
|
||||
import dev.sheldan.abstracto.core.listener.FeatureAwareListenerModel;
|
||||
import dev.sheldan.abstracto.core.models.ServerChannelMessage;
|
||||
import dev.sheldan.abstracto.core.models.ServerUser;
|
||||
import dev.sheldan.abstracto.starboard.listener.StarboardPostState;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@Builder
|
||||
public class StarboardPostUpdatedModel implements FeatureAwareListenerModel {
|
||||
private ServerChannelMessage starredMessage;
|
||||
private ServerChannelMessage starboardMessage;
|
||||
private ServerUser starredUser;
|
||||
private ServerUser lastStarrer;
|
||||
private Long starboardPostId;
|
||||
private List<Long> allStarrer;
|
||||
private StarboardPostState newState;
|
||||
|
||||
@Override
|
||||
public Long getServerId() {
|
||||
return starredUser.getServerId();
|
||||
}
|
||||
}
|
||||
@@ -2,22 +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.database.AChannel;
|
||||
import dev.sheldan.abstracto.core.models.database.AUser;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.experimental.SuperBuilder;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
import net.dv8tion.jda.api.entities.TextChannel;
|
||||
import net.dv8tion.jda.api.entities.User;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@SuperBuilder
|
||||
public class StarboardPostModel extends ServerContext {
|
||||
private Member author;
|
||||
private User author;
|
||||
private TextChannel channel;
|
||||
private AUser user;
|
||||
private AChannel aChannel;
|
||||
private Long sourceChannelId;
|
||||
private CachedMessage message;
|
||||
private Integer starCount;
|
||||
private String starLevelEmote;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package dev.sheldan.abstracto.starboard.service;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.ServerUser;
|
||||
import dev.sheldan.abstracto.core.models.cache.CachedMessage;
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.starboard.model.database.StarboardPost;
|
||||
@@ -18,4 +19,5 @@ public interface StarboardService {
|
||||
CompletableFuture<GuildStarStatsModel> retrieveStarStats(Long serverId);
|
||||
MemberStarStatsModel retrieveStarStatsForMember(Member member);
|
||||
StarStatsPost fromStarboardPost(StarboardPost starboardPost);
|
||||
void deleteStarboardPost(StarboardPost starboardPost, ServerUser userReacting);
|
||||
}
|
||||
|
||||
@@ -2,9 +2,9 @@ package dev.sheldan.abstracto.statistic.emote.listener;
|
||||
|
||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
import dev.sheldan.abstracto.core.config.FeatureMode;
|
||||
import dev.sheldan.abstracto.core.config.ListenerPriority;
|
||||
import dev.sheldan.abstracto.core.listener.DefaultListenerResult;
|
||||
import dev.sheldan.abstracto.core.listener.async.jda.AsyncEmoteCreatedListener;
|
||||
import dev.sheldan.abstracto.core.models.cache.CachedEmote;
|
||||
import dev.sheldan.abstracto.core.models.listener.EmoteCreatedModel;
|
||||
import dev.sheldan.abstracto.statistic.config.StatisticFeatureDefinition;
|
||||
import dev.sheldan.abstracto.statistic.emote.config.EmoteTrackingMode;
|
||||
import dev.sheldan.abstracto.statistic.emote.service.management.TrackedEmoteManagementService;
|
||||
@@ -28,24 +28,20 @@ public class CreateTrackedEmoteListener implements AsyncEmoteCreatedListener {
|
||||
@Autowired
|
||||
private TrackedEmoteManagementService trackedEmoteManagementService;
|
||||
|
||||
@Override
|
||||
public void emoteCreated(CachedEmote createdEmote) {
|
||||
log.info("Creating tracked emote {} in server {}.", createdEmote.getServerId(), createdEmote.getEmoteId());
|
||||
trackedEmoteManagementService.createTrackedEmote(createdEmote);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeatureDefinition getFeature() {
|
||||
return StatisticFeatureDefinition.EMOTE_TRACKING;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getPriority() {
|
||||
return ListenerPriority.MEDIUM;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<FeatureMode> getFeatureModeLimitations() {
|
||||
return Arrays.asList(EmoteTrackingMode.AUTO_TRACK);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DefaultListenerResult execute(EmoteCreatedModel model) {
|
||||
log.info("Creating tracked emote {} in server {}.", model.getServerId(), model.getEmote().getIdLong());
|
||||
trackedEmoteManagementService.createTrackedEmote(model.getEmote());
|
||||
return DefaultListenerResult.PROCESSED;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,9 +2,9 @@ package dev.sheldan.abstracto.statistic.emote.listener;
|
||||
|
||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
import dev.sheldan.abstracto.core.config.FeatureMode;
|
||||
import dev.sheldan.abstracto.core.config.ListenerPriority;
|
||||
import dev.sheldan.abstracto.core.listener.DefaultListenerResult;
|
||||
import dev.sheldan.abstracto.core.listener.async.jda.AsyncEmoteDeletedListener;
|
||||
import dev.sheldan.abstracto.core.models.cache.CachedEmote;
|
||||
import dev.sheldan.abstracto.core.models.listener.EmoteDeletedModel;
|
||||
import dev.sheldan.abstracto.statistic.config.StatisticFeatureDefinition;
|
||||
import dev.sheldan.abstracto.statistic.emote.config.EmoteTrackingMode;
|
||||
import dev.sheldan.abstracto.statistic.emote.service.management.TrackedEmoteManagementService;
|
||||
@@ -17,7 +17,7 @@ import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* This listener listens for deleted {@link Emote} in a {@link net.dv8tion.jda.api.entities.Guild} and markes respective
|
||||
* This listener listens for deleted {@link Emote} in a {@link net.dv8tion.jda.api.entities.Guild} and marks respective
|
||||
* {@link dev.sheldan.abstracto.statistic.emote.model.database.TrackedEmote} as deleted, if the EMOTE_TRACKING feature is enabled and the AUTO_TRACK
|
||||
* feature mode as well.
|
||||
*/
|
||||
@@ -28,24 +28,21 @@ public class DeleteTrackedEmoteListener implements AsyncEmoteDeletedListener {
|
||||
@Autowired
|
||||
private TrackedEmoteManagementService trackedEmoteManagementService;
|
||||
|
||||
@Override
|
||||
public void emoteDeleted(CachedEmote deletedEmote) {
|
||||
log.info("Marking tracked emote {} in gild {} as deleted.", deletedEmote.getEmoteId(), deletedEmote.getServerId());
|
||||
trackedEmoteManagementService.markAsDeleted(deletedEmote.getServerId(), deletedEmote.getEmoteId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeatureDefinition getFeature() {
|
||||
return StatisticFeatureDefinition.EMOTE_TRACKING;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getPriority() {
|
||||
return ListenerPriority.MEDIUM;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<FeatureMode> getFeatureModeLimitations() {
|
||||
return Arrays.asList(EmoteTrackingMode.AUTO_TRACK);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DefaultListenerResult execute(EmoteDeletedModel model) {
|
||||
log.info("Marking tracked emote {} in gild {} as deleted.", model.getEmote().getIdLong(), model.getServerId());
|
||||
trackedEmoteManagementService.markAsDeleted(model.getEmote());
|
||||
return DefaultListenerResult.PROCESSED;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
package dev.sheldan.abstracto.statistic.emote.listener;
|
||||
|
||||
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.cache.CachedEmote;
|
||||
import dev.sheldan.abstracto.core.models.cache.CachedMessage;
|
||||
import dev.sheldan.abstracto.core.models.listener.MessageReceivedModel;
|
||||
import dev.sheldan.abstracto.core.service.GuildService;
|
||||
import dev.sheldan.abstracto.statistic.config.StatisticFeatureDefinition;
|
||||
import dev.sheldan.abstracto.statistic.emote.service.TrackedEmoteService;
|
||||
import net.dv8tion.jda.api.entities.Emote;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@@ -27,17 +28,17 @@ public class EmoteTrackingListener implements AsyncMessageReceivedListener {
|
||||
@Autowired
|
||||
private GuildService guildService;
|
||||
|
||||
@Override
|
||||
public void execute(CachedMessage message) {
|
||||
Map<Long, List<CachedEmote>> collect = message.getEmotes().stream().collect(Collectors.groupingBy(CachedEmote::getEmoteId));
|
||||
collect.values().forEach(groupedEmotes ->
|
||||
trackedEmoteService.addEmoteToRuntimeStorage(groupedEmotes.get(0), guildService.getGuildById(message.getServerId()), (long) groupedEmotes.size())
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeatureDefinition getFeature() {
|
||||
return StatisticFeatureDefinition.EMOTE_TRACKING;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DefaultListenerResult execute(MessageReceivedModel model) {
|
||||
Map<Long, List<Emote>> collect = model.getMessage().getEmotesBag().stream().collect(Collectors.groupingBy(Emote::getIdLong));
|
||||
collect.values().forEach(groupedEmotes ->
|
||||
trackedEmoteService.addEmoteToRuntimeStorage(groupedEmotes.get(0), guildService.getGuildById(model.getServerId()), (long) groupedEmotes.size())
|
||||
);
|
||||
return DefaultListenerResult.PROCESSED;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,9 +2,9 @@ package dev.sheldan.abstracto.statistic.emote.listener;
|
||||
|
||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
import dev.sheldan.abstracto.core.config.FeatureMode;
|
||||
import dev.sheldan.abstracto.core.config.ListenerPriority;
|
||||
import dev.sheldan.abstracto.core.listener.async.jda.AsyncEmoteUpdatedListener;
|
||||
import dev.sheldan.abstracto.core.models.cache.CachedEmote;
|
||||
import dev.sheldan.abstracto.core.listener.DefaultListenerResult;
|
||||
import dev.sheldan.abstracto.core.listener.async.jda.AsyncEmoteNameUpdatedListener;
|
||||
import dev.sheldan.abstracto.core.models.listener.EmoteNameUpdatedModel;
|
||||
import dev.sheldan.abstracto.statistic.config.StatisticFeatureDefinition;
|
||||
import dev.sheldan.abstracto.statistic.emote.config.EmoteTrackingMode;
|
||||
import dev.sheldan.abstracto.statistic.emote.model.database.TrackedEmote;
|
||||
@@ -20,29 +20,25 @@ import java.util.List;
|
||||
* if the emote is tracked. This is only executed if the EMOTE_TRACKING feature is enabled,and if the AUTO_TRACK feature mode is enabled.
|
||||
*/
|
||||
@Component
|
||||
public class UpdateTrackedEmoteListener implements AsyncEmoteUpdatedListener {
|
||||
public class UpdateTrackedEmoteNameListener implements AsyncEmoteNameUpdatedListener {
|
||||
|
||||
@Autowired
|
||||
private TrackedEmoteManagementService trackedEmoteManagementService;
|
||||
|
||||
@Override
|
||||
public void emoteUpdated(CachedEmote updatedEmote, String oldValue, String newValue) {
|
||||
TrackedEmote trackedEmote = trackedEmoteManagementService.loadByEmoteId(updatedEmote.getEmoteId(), updatedEmote.getServerId());
|
||||
trackedEmoteManagementService.changeName(trackedEmote, newValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeatureDefinition getFeature() {
|
||||
return StatisticFeatureDefinition.EMOTE_TRACKING;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getPriority() {
|
||||
return ListenerPriority.MEDIUM;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<FeatureMode> getFeatureModeLimitations() {
|
||||
return Arrays.asList(EmoteTrackingMode.AUTO_TRACK);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DefaultListenerResult execute(EmoteNameUpdatedModel model) {
|
||||
TrackedEmote trackedEmote = trackedEmoteManagementService.loadByEmote(model.getEmote());
|
||||
trackedEmoteManagementService.changeName(trackedEmote, model.getNewValue());
|
||||
return DefaultListenerResult.PROCESSED;
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import dev.sheldan.abstracto.core.metric.service.CounterMetric;
|
||||
import dev.sheldan.abstracto.core.metric.service.MetricService;
|
||||
import dev.sheldan.abstracto.core.models.ServerSpecificId;
|
||||
import dev.sheldan.abstracto.core.models.cache.CachedEmote;
|
||||
import dev.sheldan.abstracto.core.service.CacheEntityService;
|
||||
import dev.sheldan.abstracto.core.service.EmoteService;
|
||||
import dev.sheldan.abstracto.core.service.FeatureModeService;
|
||||
import dev.sheldan.abstracto.core.service.GuildService;
|
||||
@@ -54,6 +55,9 @@ public class TrackedEmoteServiceBean implements TrackedEmoteService {
|
||||
@Autowired
|
||||
private MetricService metricService;
|
||||
|
||||
@Autowired
|
||||
private CacheEntityService cacheEntityService;
|
||||
|
||||
public static final String EMOTE_USAGES_TRACKED_METRIC = "emote.usages";
|
||||
private static final CounterMetric EMOTE_USAGES_TRACKED =
|
||||
CounterMetric
|
||||
@@ -82,6 +86,11 @@ public class TrackedEmoteServiceBean implements TrackedEmoteService {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addEmoteToRuntimeStorage(Emote emote, Guild guild, Long count) {
|
||||
addEmoteToRuntimeStorage(cacheEntityService.getCachedEmoteFromEmote(emote, guild), guild, count);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void storeEmoteStatistics(Map<Long, List<PersistingEmote>> usagesToStore) {
|
||||
|
||||
@@ -38,6 +38,11 @@ public class TrackedEmoteManagementServiceBean implements TrackedEmoteManagement
|
||||
return createTrackedEmote(emote.getIdLong(), emote.getName(), emote.isAnimated(), true, server);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TrackedEmote createTrackedEmote(Emote emote) {
|
||||
return createTrackedEmote(emote, emote.getGuild());
|
||||
}
|
||||
|
||||
@Override
|
||||
public TrackedEmote createTrackedEmote(CachedEmote emote) {
|
||||
AServer server = serverManagementService.loadServer(emote.getServerId());
|
||||
@@ -109,6 +114,11 @@ public class TrackedEmoteManagementServiceBean implements TrackedEmoteManagement
|
||||
markAsDeleted(emote);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void markAsDeleted(Emote emote) {
|
||||
markAsDeleted(emote.getGuild().getIdLong(), emote.getIdLong());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void markAsDeleted(TrackedEmote trackedemote) {
|
||||
log.info("Marking tracked emote {} in server {} as deleted.", trackedemote.getTrackedEmoteId().getId(), trackedemote.getTrackedEmoteId().getServerId());
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
package dev.sheldan.abstracto.statistic.emote.listener;
|
||||
|
||||
import dev.sheldan.abstracto.core.config.ListenerPriority;
|
||||
import dev.sheldan.abstracto.core.models.cache.CachedEmote;
|
||||
import dev.sheldan.abstracto.core.models.listener.EmoteCreatedModel;
|
||||
import dev.sheldan.abstracto.statistic.config.StatisticFeatureDefinition;
|
||||
import dev.sheldan.abstracto.statistic.emote.service.management.TrackedEmoteManagementService;
|
||||
import net.dv8tion.jda.api.entities.Emote;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
@@ -23,14 +23,19 @@ public class CreateTrackedEmoteListenerTest {
|
||||
@Mock
|
||||
private TrackedEmoteManagementService trackedEmoteManagementService;
|
||||
|
||||
@Mock
|
||||
private EmoteCreatedModel model;
|
||||
|
||||
private static final Long SERVER_ID = 4L;
|
||||
private static final Long EMOTE_ID = 4L;
|
||||
|
||||
@Test
|
||||
public void testEmoteCreated() {
|
||||
Long serverId = 4L;
|
||||
Long emoteId = 5L;
|
||||
CachedEmote emote = Mockito.mock(CachedEmote.class);
|
||||
when(emote.getEmoteId()).thenReturn(emoteId);
|
||||
when(emote.getServerId()).thenReturn(serverId);
|
||||
testUnit.emoteCreated(emote);
|
||||
Emote emote = Mockito.mock(Emote.class);
|
||||
when(emote.getIdLong()).thenReturn(EMOTE_ID);
|
||||
when(model.getEmote()).thenReturn(emote);
|
||||
when(model.getServerId()).thenReturn(SERVER_ID);
|
||||
testUnit.execute(model);
|
||||
verify(trackedEmoteManagementService, times(1)).createTrackedEmote(emote);
|
||||
}
|
||||
|
||||
@@ -39,8 +44,4 @@ public class CreateTrackedEmoteListenerTest {
|
||||
Assert.assertEquals(StatisticFeatureDefinition.EMOTE_TRACKING, testUnit.getFeature());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPriority() {
|
||||
Assert.assertEquals(ListenerPriority.MEDIUM, testUnit.getPriority());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
package dev.sheldan.abstracto.statistic.emote.listener;
|
||||
|
||||
import dev.sheldan.abstracto.core.config.ListenerPriority;
|
||||
import dev.sheldan.abstracto.core.models.cache.CachedEmote;
|
||||
import dev.sheldan.abstracto.core.models.listener.EmoteDeletedModel;
|
||||
import dev.sheldan.abstracto.statistic.config.StatisticFeatureDefinition;
|
||||
import dev.sheldan.abstracto.statistic.emote.service.management.TrackedEmoteManagementService;
|
||||
import net.dv8tion.jda.api.entities.Emote;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
@@ -23,15 +23,20 @@ public class DeleteTrackedEmoteListenerTest {
|
||||
@Mock
|
||||
private TrackedEmoteManagementService trackedEmoteManagementService;
|
||||
|
||||
@Mock
|
||||
private EmoteDeletedModel model;
|
||||
|
||||
private static final Long SERVER_ID = 4L;
|
||||
private static final Long EMOTE_ID = 4L;
|
||||
|
||||
@Test
|
||||
public void testEmoteDeleted() {
|
||||
Long serverId = 4L;
|
||||
Long emoteId = 5L;
|
||||
CachedEmote emote = Mockito.mock(CachedEmote.class);
|
||||
when(emote.getEmoteId()).thenReturn(emoteId);
|
||||
when(emote.getServerId()).thenReturn(serverId);
|
||||
testUnit.emoteDeleted(emote);
|
||||
verify(trackedEmoteManagementService, times(1)).markAsDeleted(serverId, emoteId);
|
||||
Emote emote = Mockito.mock(Emote.class);
|
||||
when(emote.getIdLong()).thenReturn(EMOTE_ID);
|
||||
when(model.getEmote()).thenReturn(emote);
|
||||
when(model.getServerId()).thenReturn(SERVER_ID);
|
||||
testUnit.execute(model);
|
||||
verify(trackedEmoteManagementService, times(1)).markAsDeleted(SERVER_ID, EMOTE_ID);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -39,8 +44,4 @@ public class DeleteTrackedEmoteListenerTest {
|
||||
Assert.assertEquals(StatisticFeatureDefinition.EMOTE_TRACKING, testUnit.getFeature());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPriority() {
|
||||
Assert.assertEquals(ListenerPriority.MEDIUM, testUnit.getPriority());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
package dev.sheldan.abstracto.statistic.emote.listener;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.cache.CachedEmote;
|
||||
import dev.sheldan.abstracto.core.models.cache.CachedMessage;
|
||||
import dev.sheldan.abstracto.core.models.listener.MessageReceivedModel;
|
||||
import dev.sheldan.abstracto.core.service.GuildService;
|
||||
import dev.sheldan.abstracto.statistic.config.StatisticFeatureDefinition;
|
||||
import dev.sheldan.abstracto.statistic.emote.service.TrackedEmoteService;
|
||||
import net.dv8tion.jda.api.entities.Emote;
|
||||
import net.dv8tion.jda.api.entities.Guild;
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
@@ -31,13 +33,16 @@ public class EmoteTrackingListenerTest {
|
||||
private GuildService guildService;
|
||||
|
||||
@Mock
|
||||
private CachedMessage message;
|
||||
private Message message;
|
||||
|
||||
@Mock
|
||||
private CachedEmote emote1;
|
||||
private MessageReceivedModel messageReceivedModel;
|
||||
|
||||
@Mock
|
||||
private CachedEmote emote2;
|
||||
private Emote emote1;
|
||||
|
||||
@Mock
|
||||
private Emote emote2;
|
||||
|
||||
@Mock
|
||||
private Guild guild;
|
||||
@@ -47,40 +52,43 @@ public class EmoteTrackingListenerTest {
|
||||
|
||||
@Test
|
||||
public void testExecuteOneEmote() {
|
||||
List<CachedEmote> emotesBag = new ArrayList<>();
|
||||
List<Emote> emotesBag = new ArrayList<>();
|
||||
emotesBag.add(emote1);
|
||||
when(guildService.getGuildById(SERVER_ID)).thenReturn(guild);
|
||||
when(message.getServerId()).thenReturn(SERVER_ID);
|
||||
when(messageReceivedModel.getMessage()).thenReturn(message);
|
||||
when(messageReceivedModel.getServerId()).thenReturn(SERVER_ID);
|
||||
when(message.getEmotes()).thenReturn(emotesBag);
|
||||
testUnit.execute(message);
|
||||
testUnit.execute(messageReceivedModel);
|
||||
verify(trackedEmoteService, times(1)).addEmoteToRuntimeStorage(emote1, guild, 1L);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExecuteOneEmoteMultipleTimes() {
|
||||
List<CachedEmote> emotesBag = new ArrayList<>();
|
||||
when(emote1.getEmoteId()).thenReturn(EMOTE_ID);
|
||||
when(emote2.getEmoteId()).thenReturn(EMOTE_ID);
|
||||
List<Emote> emotesBag = new ArrayList<>();
|
||||
when(emote1.getIdLong()).thenReturn(EMOTE_ID);
|
||||
when(emote2.getIdLong()).thenReturn(EMOTE_ID);
|
||||
emotesBag.add(emote1);
|
||||
emotesBag.add(emote2);
|
||||
when(guildService.getGuildById(SERVER_ID)).thenReturn(guild);
|
||||
when(message.getServerId()).thenReturn(SERVER_ID);
|
||||
when(messageReceivedModel.getServerId()).thenReturn(SERVER_ID);
|
||||
when(messageReceivedModel.getMessage()).thenReturn(message);
|
||||
when(message.getEmotes()).thenReturn(emotesBag);
|
||||
testUnit.execute(message);
|
||||
testUnit.execute(messageReceivedModel);
|
||||
verify(trackedEmoteService, times(1)).addEmoteToRuntimeStorage(any(CachedEmote.class), eq(guild), eq(2L));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExecuteMultipleEmotes() {
|
||||
List<CachedEmote> emotesBag = new ArrayList<>();
|
||||
when(emote1.getEmoteId()).thenReturn(EMOTE_ID);
|
||||
when(emote2.getEmoteId()).thenReturn(EMOTE_ID + 1);
|
||||
List<Emote> emotesBag = new ArrayList<>();
|
||||
when(emote1.getIdLong()).thenReturn(EMOTE_ID);
|
||||
when(emote2.getIdLong()).thenReturn(EMOTE_ID + 1);
|
||||
emotesBag.add(emote1);
|
||||
emotesBag.add(emote2);
|
||||
when(guildService.getGuildById(SERVER_ID)).thenReturn(guild);
|
||||
when(message.getServerId()).thenReturn(SERVER_ID);
|
||||
when(messageReceivedModel.getServerId()).thenReturn(SERVER_ID);
|
||||
when(messageReceivedModel.getMessage()).thenReturn(message);
|
||||
when(message.getEmotes()).thenReturn(emotesBag);
|
||||
testUnit.execute(message);
|
||||
testUnit.execute(messageReceivedModel);
|
||||
verify(trackedEmoteService, times(1)).addEmoteToRuntimeStorage(emote1, guild, 1L);
|
||||
verify(trackedEmoteService, times(1)).addEmoteToRuntimeStorage(emote2, guild, 1L);
|
||||
}
|
||||
@@ -88,8 +96,9 @@ public class EmoteTrackingListenerTest {
|
||||
@Test
|
||||
public void testExecuteNoEmote() {
|
||||
when(message.getEmotes()).thenReturn(new ArrayList<>());
|
||||
testUnit.execute(message);
|
||||
verify(trackedEmoteService, times(0)).addEmoteToRuntimeStorage(any(), any(), anyLong());
|
||||
when(messageReceivedModel.getMessage()).thenReturn(message);
|
||||
testUnit.execute(messageReceivedModel);
|
||||
verify(trackedEmoteService, times(0)).addEmoteToRuntimeStorage(any(Emote.class), any(), anyLong());
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
package dev.sheldan.abstracto.statistic.emote.listener;
|
||||
|
||||
import dev.sheldan.abstracto.core.config.ListenerPriority;
|
||||
import dev.sheldan.abstracto.core.models.cache.CachedEmote;
|
||||
import dev.sheldan.abstracto.core.models.listener.EmoteNameUpdatedModel;
|
||||
import dev.sheldan.abstracto.statistic.config.StatisticFeatureDefinition;
|
||||
import dev.sheldan.abstracto.statistic.emote.model.database.TrackedEmote;
|
||||
import dev.sheldan.abstracto.statistic.emote.service.management.TrackedEmoteManagementService;
|
||||
import net.dv8tion.jda.api.entities.Emote;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
@@ -19,22 +19,26 @@ import static org.mockito.Mockito.*;
|
||||
public class UpdateTrackedEmoteListenerTest {
|
||||
|
||||
@InjectMocks
|
||||
private UpdateTrackedEmoteListener testUnit;
|
||||
private UpdateTrackedEmoteNameListener testUnit;
|
||||
|
||||
@Mock
|
||||
private TrackedEmoteManagementService trackedEmoteManagementService;
|
||||
|
||||
@Mock
|
||||
private EmoteNameUpdatedModel model;
|
||||
|
||||
@Test
|
||||
public void testEmoteUpdated() {
|
||||
Long serverId = 1L;
|
||||
Long emoteId = 2L;
|
||||
CachedEmote changedEmote = Mockito.mock(CachedEmote.class);
|
||||
when(changedEmote.getServerId()).thenReturn(serverId);
|
||||
when(changedEmote.getEmoteId()).thenReturn(emoteId);
|
||||
Emote changedEmote = Mockito.mock(Emote.class);
|
||||
when(changedEmote.getIdLong()).thenReturn(emoteId);
|
||||
TrackedEmote trackedEmote = Mockito.mock(TrackedEmote.class);
|
||||
when(trackedEmoteManagementService.loadByEmoteId(emoteId, serverId)).thenReturn(trackedEmote);
|
||||
String newValue = "AFTER";
|
||||
testUnit.emoteUpdated(changedEmote, "BEFORE", newValue);
|
||||
when(model.getEmote()).thenReturn(changedEmote);
|
||||
when(model.getNewValue()).thenReturn(newValue);
|
||||
testUnit.execute(model);
|
||||
verify(trackedEmoteManagementService, times(1)).changeName(trackedEmote, newValue);
|
||||
}
|
||||
|
||||
@@ -43,8 +47,4 @@ public class UpdateTrackedEmoteListenerTest {
|
||||
Assert.assertEquals(StatisticFeatureDefinition.EMOTE_TRACKING, testUnit.getFeature());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPriority() {
|
||||
Assert.assertEquals(ListenerPriority.MEDIUM, testUnit.getPriority());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,6 +31,14 @@ public interface TrackedEmoteService {
|
||||
*/
|
||||
void addEmoteToRuntimeStorage(CachedEmote emote, Guild guild, Long count);
|
||||
|
||||
/**
|
||||
* Adds the given {@link Emote} with the given amount to the runtime storage for the given {@link Guild}
|
||||
* @param emote The {@link Emote} to add to the runtime storage
|
||||
* @param guild The {@link Guild} in which the {@link Emote} was used and in which the usage should be added
|
||||
* @param count The amount of times which the {@link Emote} has been used and should be reflected in the runtime storage
|
||||
*/
|
||||
void addEmoteToRuntimeStorage(Emote emote, Guild guild, Long count);
|
||||
|
||||
/**
|
||||
* Takes the given map of server_ids with the list of {@link PersistingEmote} and stores the objects in the database
|
||||
* Non existing {@link TrackedEmote} for the server will be created. Depending on the feature mode external emotes will be created.
|
||||
|
||||
@@ -34,6 +34,15 @@ public interface TrackedEmoteManagementService {
|
||||
*/
|
||||
TrackedEmote createTrackedEmote(Emote emote, Guild guild);
|
||||
|
||||
/**
|
||||
* Creates and persists a {@link TrackedEmote} for which tracking is enabled based on the given {@link Emote}.
|
||||
* The emote used here must contain a {@link Guild guild} instance, emotes created from {@link net.dv8tion.jda.api.entities.Message messages}
|
||||
* do not.
|
||||
* @param emote The {@link Emote} to be used to create a {@link TrackedEmote}
|
||||
* @return The created {@link TrackedEmote} instance in the database
|
||||
*/
|
||||
TrackedEmote createTrackedEmote(Emote emote);
|
||||
|
||||
/**
|
||||
* Creates and persists a {@link TrackedEmote} for which tracking is enabled based on the given {@link Emote} and {@link Guild}
|
||||
* @param emote The {@link CachedEmote} to be used to create a {@link TrackedEmote}
|
||||
@@ -106,6 +115,14 @@ public interface TrackedEmoteManagementService {
|
||||
*/
|
||||
void markAsDeleted(Long serverId, Long emoteId);
|
||||
|
||||
/**
|
||||
* Marks the {@link Emote emote} as deleted in the database. This {@link Emote emote} must
|
||||
* not come from a {@link net.dv8tion.jda.api.entities.Message message}, because then the {@link Guild guild}
|
||||
* is null.
|
||||
* @throws TrackedEmoteNotFoundException if no {@link TrackedEmote} with the given IDs can be found
|
||||
*/
|
||||
void markAsDeleted(Emote emote);
|
||||
|
||||
/**
|
||||
* Marks the given {@link TrackedEmote} as deleted
|
||||
* @param trackedEmote The {@link TrackedEmote} which should be marked as deleted
|
||||
|
||||
@@ -56,8 +56,7 @@ public class SuggestionManagementServiceBean implements SuggestionManagementServ
|
||||
.build();
|
||||
log.info("Persisting suggestion {} at message {} in channel {} on server {} from user {}.",
|
||||
suggestionId, message.getId(), channelId, message.getGuild().getId(), suggester.getUserReference().getId());
|
||||
suggestionRepository.save(suggestion);
|
||||
return suggestion;
|
||||
return suggestionRepository.save(suggestion);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -16,6 +16,12 @@
|
||||
<artifactId>core-impl</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>dev.sheldan.abstracto.core</groupId>
|
||||
<artifactId>core-int</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<!-- modules containing commands -->
|
||||
|
||||
<dependency>
|
||||
@@ -24,83 +30,167 @@
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>moderation-int</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>modmail-impl</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>modmail-int</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>utility-impl</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>utility-int</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>experience-tracking-impl</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>experience-tracking-int</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>dev.sheldan.abstracto.scheduling</groupId>
|
||||
<artifactId>scheduling-impl</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>dev.sheldan.abstracto.scheduling</groupId>
|
||||
<artifactId>scheduling-int</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>assignable-roles-impl</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>assignable-roles-int</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>statistic-impl</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>statistic-int</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>dev.sheldan.abstracto.core</groupId>
|
||||
<artifactId>metrics-impl</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>dev.sheldan.abstracto.core</groupId>
|
||||
<artifactId>metrics-int</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>entertainment-impl</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>entertainment-int</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>link-embed-impl</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>link-embed-int</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>remind-impl</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>remind-int</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>repost-detection-impl</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>repost-detection-int</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>starboard-impl</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>starboard-int</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>suggestion-impl</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>suggestion-int</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
|
||||
@@ -4,8 +4,11 @@ import dev.sheldan.abstracto.core.command.Command;
|
||||
import dev.sheldan.abstracto.core.command.models.database.ACommand;
|
||||
import dev.sheldan.abstracto.core.command.service.management.CommandInServerManagementService;
|
||||
import dev.sheldan.abstracto.core.command.service.management.CommandManagementService;
|
||||
import dev.sheldan.abstracto.core.listener.sync.entity.ServerConfigListener;
|
||||
import dev.sheldan.abstracto.core.listener.DefaultListenerResult;
|
||||
import dev.sheldan.abstracto.core.listener.async.entity.AsyncServerCreatedListener;
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import dev.sheldan.abstracto.core.models.listener.ServerCreatedListenerModel;
|
||||
import dev.sheldan.abstracto.core.service.management.ServerManagementService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
@@ -14,7 +17,7 @@ import java.util.List;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class CommandConfigListener implements ServerConfigListener {
|
||||
public class CommandConfigListenerAsync implements AsyncServerCreatedListener {
|
||||
|
||||
@Autowired
|
||||
private List<Command> commandList;
|
||||
@@ -25,9 +28,13 @@ public class CommandConfigListener implements ServerConfigListener {
|
||||
@Autowired
|
||||
private CommandManagementService commandManagementService;
|
||||
|
||||
@Autowired
|
||||
private ServerManagementService serverManagementService;
|
||||
|
||||
@Override
|
||||
public void updateServerConfig(AServer server) {
|
||||
log.info("Creating command instances for server {}.", server.getId());
|
||||
public DefaultListenerResult execute(ServerCreatedListenerModel model) {
|
||||
AServer server = serverManagementService.loadServer(model.getServerId());
|
||||
log.info("Creating command instances for server {}.", model.getServerId());
|
||||
commandList.forEach(command -> {
|
||||
if(command.getConfiguration() != null) {
|
||||
ACommand aCommand = commandManagementService.findCommandByName(command.getConfiguration().getName());
|
||||
@@ -36,5 +43,6 @@ public class CommandConfigListener implements ServerConfigListener {
|
||||
}
|
||||
}
|
||||
});
|
||||
return DefaultListenerResult.PROCESSED;
|
||||
}
|
||||
}
|
||||
@@ -40,8 +40,7 @@ public class ChannelGroupCommandManagementServiceBean implements ChannelGroupCom
|
||||
|
||||
log.info("Creating command {} in group {}.", command.getName(), group.getId());
|
||||
|
||||
groupCommandRepository.save(channelGroupCommand);
|
||||
return channelGroupCommand;
|
||||
return groupCommandRepository.save(channelGroupCommand);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -24,9 +24,8 @@ public class CommandInServerManagementServiceBean implements CommandInServerMana
|
||||
.serverReference(server)
|
||||
.restricted(false)
|
||||
.build();
|
||||
repository.save(commandInAServer);
|
||||
log.info("Creating command {} in server {}.", command.getName(), server.getId());
|
||||
return commandInAServer;
|
||||
return repository.save(commandInAServer);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -40,8 +40,7 @@ public class CommandManagementServiceBean implements CommandManagementService {
|
||||
.feature(feature)
|
||||
.build();
|
||||
log.info("Creating creating command {} in module {} with feature {}.", name, module.getName(), feature.getKey());
|
||||
commandRepository.save(command);
|
||||
return command;
|
||||
return commandRepository.save(command);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -19,9 +19,8 @@ public class ModuleManagementServiceBean implements ModuleManagementService {
|
||||
builder()
|
||||
.name(name)
|
||||
.build();
|
||||
moduleRepository.save(module);
|
||||
log.info("Creating module {}.", name);
|
||||
return module;
|
||||
return moduleRepository.save(module);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,117 +1,82 @@
|
||||
package dev.sheldan.abstracto.core.config;
|
||||
|
||||
import dev.sheldan.abstracto.core.service.ExecutorService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.core.task.TaskExecutor;
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
||||
|
||||
@Configuration
|
||||
public class ListenerExecutorConfig {
|
||||
|
||||
@Value("${abstracto.listener.default.maxPoolSize}")
|
||||
private Integer defaultMaxPoolSize;
|
||||
|
||||
@Value("${abstracto.listener.default.corePoolSize}")
|
||||
private Integer defaultCorePoolSize;
|
||||
|
||||
@Value("${abstracto.listener.default.keepAliveSeconds}")
|
||||
private Integer defaultKeepAliveSeconds;
|
||||
|
||||
@Autowired
|
||||
private Environment environment;
|
||||
|
||||
private static final String LISTENER_PREFIX = "abstracto.listener.";
|
||||
private static final String LISTENER_MAX_POOL_SIZE = "maxPoolSize";
|
||||
private static final String LISTENER_CORE_POOL_SIZE = "corePoolSize";
|
||||
private static final String LISTENER_KEEP_ALIVE_SECONDS = "keepAliveSeconds";
|
||||
private ExecutorService executorService;
|
||||
|
||||
@Bean(name = "joinListenerExecutor")
|
||||
public TaskExecutor joinListenerExecutor() {
|
||||
return setupExecutorFor("joinListener");
|
||||
return executorService.setupExecutorFor("joinListener");
|
||||
}
|
||||
|
||||
@Bean(name = "leaveListenerExecutor")
|
||||
public TaskExecutor leaveListenerExecutor() {
|
||||
return setupExecutorFor("leaveListener");
|
||||
return executorService.setupExecutorFor("leaveListener");
|
||||
}
|
||||
|
||||
@Bean(name = "messageReceivedExecutor")
|
||||
public TaskExecutor messageReceivedExecutor() {
|
||||
return setupExecutorFor("messageReceivedListener");
|
||||
return executorService.setupExecutorFor("messageReceivedListener");
|
||||
}
|
||||
|
||||
@Bean(name = "messageDeletedExecutor")
|
||||
public TaskExecutor messageDeletedExecutor() {
|
||||
return setupExecutorFor("messageReceivedListener");
|
||||
return executorService.setupExecutorFor("messageReceivedListener");
|
||||
}
|
||||
|
||||
@Bean(name = "messageEmbeddedExecutor")
|
||||
public TaskExecutor messageEmbeddedExecutor() {
|
||||
return setupExecutorFor("messageEmbeddedListener");
|
||||
return executorService.setupExecutorFor("messageEmbeddedListener");
|
||||
}
|
||||
|
||||
@Bean(name = "messageUpdatedExecutor")
|
||||
public TaskExecutor messageUpdatedExecutor() {
|
||||
return setupExecutorFor("messageUpdatedListener");
|
||||
return executorService.setupExecutorFor("messageUpdatedListener");
|
||||
}
|
||||
|
||||
@Bean(name = "privateMessageReceivedExecutor")
|
||||
public TaskExecutor privateMessageReceivedExecutor() {
|
||||
return setupExecutorFor("privateMessageReceivedListener");
|
||||
return executorService.setupExecutorFor("privateMessageReceivedListener");
|
||||
}
|
||||
|
||||
@Bean(name = "emoteCreatedExecutor")
|
||||
public TaskExecutor emoteCreatedExecutor() {
|
||||
return setupExecutorFor("emoteCreatedListener");
|
||||
return executorService.setupExecutorFor("emoteCreatedListener");
|
||||
}
|
||||
|
||||
@Bean(name = "emoteDeletedExecutor")
|
||||
public TaskExecutor emoteDeletedExecutor() {
|
||||
return setupExecutorFor("emoteDeletedListener");
|
||||
return executorService.setupExecutorFor("emoteDeletedListener");
|
||||
}
|
||||
|
||||
@Bean(name = "emoteUpdatedExecutor")
|
||||
public TaskExecutor emoteUpdatedExecutor() {
|
||||
return setupExecutorFor("emoteUpdatedListener");
|
||||
return executorService.setupExecutorFor("emoteUpdatedListener");
|
||||
}
|
||||
|
||||
@Bean(name = "reactionAddedExecutor")
|
||||
public TaskExecutor reactionAddedExecutor() {
|
||||
return setupExecutorFor("reactionAddedListener");
|
||||
return executorService.setupExecutorFor("reactionAddedListener");
|
||||
}
|
||||
|
||||
@Bean(name = "reactionRemovedExecutor")
|
||||
public TaskExecutor reactionRemovedExecutor() {
|
||||
return setupExecutorFor("reactionRemovedListener");
|
||||
return executorService.setupExecutorFor("reactionRemovedListener");
|
||||
}
|
||||
|
||||
@Bean(name = "reactionClearedExecutor")
|
||||
public TaskExecutor reactionClearedExecutor() {
|
||||
return setupExecutorFor("reactionClearedListener");
|
||||
return executorService.setupExecutorFor("reactionClearedListener");
|
||||
}
|
||||
|
||||
public ThreadPoolTaskExecutor setupExecutorFor(String listenerName) {
|
||||
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
|
||||
Integer maxPoolSize = getPropertyValueInteger(listenerName, LISTENER_MAX_POOL_SIZE, defaultMaxPoolSize.toString());
|
||||
Integer corePoolSize = getPropertyValueInteger(listenerName, LISTENER_CORE_POOL_SIZE, defaultCorePoolSize.toString());
|
||||
Integer keepAliveSeconds = getPropertyValueInteger(listenerName, LISTENER_KEEP_ALIVE_SECONDS, defaultKeepAliveSeconds.toString());
|
||||
executor.setCorePoolSize(corePoolSize);
|
||||
executor.setMaxPoolSize(maxPoolSize);
|
||||
executor.setKeepAliveSeconds(keepAliveSeconds);
|
||||
executor.setThreadNamePrefix(listenerName + "-task-executor-thread");
|
||||
executor.initialize();
|
||||
return executor;
|
||||
}
|
||||
|
||||
public String getPropertyValue(String listenerName, String key, String defaultValue) {
|
||||
return environment.getProperty(LISTENER_PREFIX + listenerName + "." + key, defaultValue);
|
||||
}
|
||||
|
||||
public Integer getPropertyValueInteger(String listenerName, String key, String defaultValue) {
|
||||
return Integer.parseInt(getPropertyValue(listenerName, key, defaultValue));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,47 +1,51 @@
|
||||
package dev.sheldan.abstracto.core.listener.sync.jda;
|
||||
package dev.sheldan.abstracto.core.listener.async.entity;
|
||||
|
||||
import dev.sheldan.abstracto.core.listener.ListenerService;
|
||||
import dev.sheldan.abstracto.core.models.database.AChannelType;
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import dev.sheldan.abstracto.core.models.listener.AChannelCreatedListenerModel;
|
||||
import dev.sheldan.abstracto.core.service.management.ChannelManagementService;
|
||||
import dev.sheldan.abstracto.core.service.management.ServerManagementService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.dv8tion.jda.api.entities.TextChannel;
|
||||
import net.dv8tion.jda.api.events.channel.text.TextChannelCreateEvent;
|
||||
import net.dv8tion.jda.api.events.channel.text.TextChannelDeleteEvent;
|
||||
import net.dv8tion.jda.api.hooks.ListenerAdapter;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Isolation;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.event.TransactionalEventListener;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
@Component
|
||||
@Slf4j
|
||||
public class ChannelListener extends ListenerAdapter {
|
||||
public class AsyncAChannelCreatedListenerBean extends ListenerAdapter {
|
||||
|
||||
@Autowired(required = false)
|
||||
private List<AsyncAChannelCreatedListener> channelListener;
|
||||
|
||||
@Autowired
|
||||
private ServerManagementService serverManagementService;
|
||||
|
||||
@Autowired
|
||||
private ListenerService listenerService;
|
||||
|
||||
@Autowired
|
||||
private ChannelManagementService channelManagementService;
|
||||
|
||||
// TODO move this to a separate sync listener, which implements a a generic channel listener, in order to provide
|
||||
// the channel listener for other implementations
|
||||
@Override
|
||||
@Transactional(isolation = Isolation.SERIALIZABLE)
|
||||
public void onTextChannelDelete(@Nonnull TextChannelDeleteEvent event) {
|
||||
log.info("Handling channel delete event. Marking channel {} as deleted in server {}", event.getChannel().getIdLong(), event.getGuild().getIdLong());
|
||||
channelManagementService.markAsDeleted(event.getChannel().getIdLong());
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(isolation = Isolation.SERIALIZABLE)
|
||||
public void onTextChannelCreate(@Nonnull TextChannelCreateEvent event) {
|
||||
log.info("Handling channel created event. Creating channel {} in server {}", event.getChannel().getIdLong(), event.getGuild().getIdLong());
|
||||
AServer serverObject = serverManagementService.loadOrCreate(event.getGuild().getIdLong());
|
||||
log.info("Creating text channel with ID {}.", event.getChannel().getIdLong());
|
||||
AServer serverObject = serverManagementService.loadOrCreate(event.getChannel().getGuild().getIdLong());
|
||||
TextChannel createdChannel = event.getChannel();
|
||||
AChannelType type = AChannelType.getAChannelType(createdChannel.getType());
|
||||
channelManagementService.createChannel(createdChannel.getIdLong(), type, serverObject);
|
||||
}
|
||||
|
||||
@TransactionalEventListener
|
||||
public void executeServerCreationListener(AChannelCreatedListenerModel model) {
|
||||
if(channelListener == null) return;
|
||||
channelListener.forEach(serverCreatedListener -> listenerService.executeListener(serverCreatedListener, model));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package dev.sheldan.abstracto.core.listener.async.entity;
|
||||
|
||||
import dev.sheldan.abstracto.core.listener.ListenerService;
|
||||
import dev.sheldan.abstracto.core.models.listener.AChannelDeletedListenerModel;
|
||||
import dev.sheldan.abstracto.core.service.management.ChannelManagementService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.dv8tion.jda.api.events.channel.text.TextChannelDeleteEvent;
|
||||
import net.dv8tion.jda.api.hooks.ListenerAdapter;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.event.TransactionalEventListener;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class AsyncAChannelDeletedListenerBean extends ListenerAdapter {
|
||||
|
||||
@Autowired(required = false)
|
||||
private List<AsyncAChannelDeletedListener> channelDeletedListeners;
|
||||
|
||||
@Autowired
|
||||
private ListenerService listenerService;
|
||||
|
||||
@Autowired
|
||||
private ChannelManagementService channelManagementService;
|
||||
|
||||
@Override
|
||||
public void onTextChannelDelete(@Nonnull TextChannelDeleteEvent event) {
|
||||
channelManagementService.markAsDeleted(event.getChannel().getIdLong());
|
||||
}
|
||||
|
||||
@TransactionalEventListener
|
||||
public void executeServerCreationListener(AChannelDeletedListenerModel model) {
|
||||
if(channelDeletedListeners == null) return;
|
||||
channelDeletedListeners.forEach(serverCreatedListener -> listenerService.executeListener(serverCreatedListener, model));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package dev.sheldan.abstracto.core.listener.async.entity;
|
||||
|
||||
import dev.sheldan.abstracto.core.listener.ListenerService;
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import dev.sheldan.abstracto.core.models.listener.ARoleCreatedListenerModel;
|
||||
import dev.sheldan.abstracto.core.service.management.RoleManagementService;
|
||||
import dev.sheldan.abstracto.core.service.management.ServerManagementService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.dv8tion.jda.api.events.role.RoleCreateEvent;
|
||||
import net.dv8tion.jda.api.hooks.ListenerAdapter;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.event.TransactionalEventListener;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class AsyncARoleCreatedListenerBean extends ListenerAdapter {
|
||||
|
||||
@Autowired(required = false)
|
||||
private List<AsyncARoleCreatedListener> roleCreatedListeners;
|
||||
|
||||
@Autowired
|
||||
private ServerManagementService serverManagementService;
|
||||
|
||||
@Autowired
|
||||
private ListenerService listenerService;
|
||||
|
||||
@Autowired
|
||||
private RoleManagementService roleManagementService;
|
||||
|
||||
@Override
|
||||
public void onRoleCreate(@Nonnull RoleCreateEvent event) {
|
||||
AServer server = serverManagementService.loadServer(event.getGuild());
|
||||
roleManagementService.createRole(event.getRole().getIdLong(), server);
|
||||
}
|
||||
|
||||
@TransactionalEventListener
|
||||
public void executeServerCreationListener(ARoleCreatedListenerModel model) {
|
||||
if(roleCreatedListeners == null) return;
|
||||
roleCreatedListeners.forEach(asyncServerCreatedListener -> listenerService.executeListener(asyncServerCreatedListener, model));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package dev.sheldan.abstracto.core.listener.async.entity;
|
||||
|
||||
import dev.sheldan.abstracto.core.listener.ListenerService;
|
||||
import dev.sheldan.abstracto.core.models.listener.ARoleDeletedListenerModel;
|
||||
import dev.sheldan.abstracto.core.service.management.RoleManagementService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.dv8tion.jda.api.events.role.RoleDeleteEvent;
|
||||
import net.dv8tion.jda.api.hooks.ListenerAdapter;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.event.TransactionalEventListener;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class AsyncARoleDeletedListenerBean extends ListenerAdapter {
|
||||
|
||||
@Autowired(required = false)
|
||||
private List<AsyncARoleDeletedListener> roleDeletedListeners;
|
||||
|
||||
@Autowired
|
||||
private RoleManagementService roleManagementService;
|
||||
|
||||
@Autowired
|
||||
private ListenerService listenerService;
|
||||
|
||||
@Override
|
||||
public void onRoleDelete(@Nonnull RoleDeleteEvent event) {
|
||||
roleManagementService.markDeleted(event.getRole().getIdLong());
|
||||
}
|
||||
|
||||
@TransactionalEventListener
|
||||
public void executeServerCreationListener(ARoleDeletedListenerModel model) {
|
||||
if(roleDeletedListeners == null) return;
|
||||
roleDeletedListeners.forEach(serverCreatedListener -> listenerService.executeListener(serverCreatedListener, model));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package dev.sheldan.abstracto.core.listener.async.entity;
|
||||
|
||||
import dev.sheldan.abstracto.core.listener.ListenerService;
|
||||
import dev.sheldan.abstracto.core.listener.sync.entity.AsyncChannelGroupCreatedListener;
|
||||
import dev.sheldan.abstracto.core.models.listener.ChannelGroupCreatedListenerModel;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.event.TransactionalEventListener;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
public class AsyncChannelGroupCreatedListenerManager {
|
||||
@Autowired(required = false)
|
||||
private List<AsyncChannelGroupCreatedListener> listener;
|
||||
|
||||
@Autowired
|
||||
private ListenerService listenerService;
|
||||
|
||||
@TransactionalEventListener
|
||||
public void executeListener(ChannelGroupCreatedListenerModel createdGroup){
|
||||
listener.forEach(asyncChannelGroupCreatedListener ->
|
||||
listenerService.executeListener(asyncChannelGroupCreatedListener, createdGroup)
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package dev.sheldan.abstracto.core.listener.async.entity;
|
||||
|
||||
import dev.sheldan.abstracto.core.listener.ListenerService;
|
||||
import dev.sheldan.abstracto.core.listener.sync.entity.AsyncChannelGroupDeletedListener;
|
||||
import dev.sheldan.abstracto.core.models.listener.ChannelGroupDeletedListenerModel;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.event.TransactionalEventListener;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
public class AsyncChannelGroupDeletedListenerManager {
|
||||
@Autowired(required = false)
|
||||
private List<AsyncChannelGroupDeletedListener> listener;
|
||||
|
||||
@Autowired
|
||||
private ListenerService listenerService;
|
||||
|
||||
@TransactionalEventListener
|
||||
public void executeListener(ChannelGroupDeletedListenerModel model){
|
||||
listener.forEach(channelGroupCreatedListener ->
|
||||
listenerService.executeListener(channelGroupCreatedListener, model)
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user