[AB-94] adding possibility to reference member/role/channel via name for parameters

showing an embed for parameter handling exceptions
adding discord webhook for build status
This commit is contained in:
Sheldan
2021-02-20 23:17:21 +01:00
parent a20fe82e15
commit 9db5889160
12 changed files with 168 additions and 38 deletions

View File

@@ -39,3 +39,15 @@ jobs:
-Dsonar.java.binaries=**/target/classes
-Dsonar.coverage.jacoco.xmlReportPaths=abstracto-application/coverage/target/site/jacoco-aggregate/jacoco.xml
-Dsonar.coverage.exclusions=**/*Test.java
- uses: actions/setup-ruby@v1
- name: Send Webhook Notification
if: always()
env:
JOB_STATUS: ${{ job.status }}
WEBHOOK_URL: ${{ secrets.WEBHOOK_URL }}
HOOK_OS_NAME: ${{ runner.os }}
WORKFLOW_NAME: ${{ github.workflow }}
run: |
git clone https://github.com/DiscordHooks/github-actions-discord-webhook.git webhook
bash webhook/send.sh $JOB_STATUS $WEBHOOK_URL
shell: bash

View File

@@ -1,12 +1,15 @@
package dev.sheldan.abstracto.core.command.handler;
import dev.sheldan.abstracto.core.command.CommandConstants;
import dev.sheldan.abstracto.core.command.exception.AbstractoTemplatedException;
import dev.sheldan.abstracto.core.command.execution.UnparsedCommandParameterPiece;
import dev.sheldan.abstracto.core.command.handler.provided.MemberParameterHandler;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.Message;
import org.apache.commons.lang3.math.NumberUtils;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.regex.Matcher;
@@ -29,9 +32,20 @@ public class MemberParameterHandlerImpl implements MemberParameterHandler {
if(matcher.matches()) {
return CompletableFuture.completedFuture(iterators.getMemberIterator().next());
} else {
// TODO add handling for names
long userId = Long.parseLong(inputString);
return context.getGuild().retrieveMemberById(userId).submit().thenApply(member -> member);
if(NumberUtils.isParsable(inputString)) {
long userId = Long.parseLong(inputString);
return context.getGuild().retrieveMemberById(userId).submit().thenApply(member -> member);
} else {
List<Member> possibleMembers = context.getGuild().getMembersByName(inputString, true);
if(possibleMembers.isEmpty()) {
throw new AbstractoTemplatedException("No member found with name.", "no_member_found_by_name_exception");
}
if(possibleMembers.size() > 1) {
throw new AbstractoTemplatedException("Multiple members found with name.", "multiple_members_found_by_name_exception");
}
return CompletableFuture.completedFuture(possibleMembers.get(0));
}
}
}

View File

@@ -1,12 +1,15 @@
package dev.sheldan.abstracto.core.command.handler;
import dev.sheldan.abstracto.core.command.CommandConstants;
import dev.sheldan.abstracto.core.command.exception.AbstractoTemplatedException;
import dev.sheldan.abstracto.core.command.execution.UnparsedCommandParameterPiece;
import dev.sheldan.abstracto.core.command.handler.provided.RoleParameterHandler;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.Role;
import org.apache.commons.lang3.math.NumberUtils;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.regex.Matcher;
@Component
@@ -23,8 +26,19 @@ public class RoleParameterHandlerImpl implements RoleParameterHandler {
if(matcher.matches()) {
return iterators.getRoleIterator().next();
} else {
long roleId = Long.parseLong(inputString);
return context.getGuild().getRoleById(roleId);
if(NumberUtils.isParsable(inputString)) {
long roleId = Long.parseLong(inputString);
return context.getGuild().getRoleById(roleId);
} else {
List<Role> roles = context.getGuild().getRolesByName(inputString, true);
if(roles.isEmpty()) {
throw new AbstractoTemplatedException("No role found with name.", "no_role_found_by_name_exception");
}
if(roles.size() > 1) {
throw new AbstractoTemplatedException("Multiple roles found with name.", "multiple_roles_found_by_name_exception");
}
return roles.get(0);
}
}
}

View File

@@ -1,12 +1,15 @@
package dev.sheldan.abstracto.core.command.handler;
import dev.sheldan.abstracto.core.command.CommandConstants;
import dev.sheldan.abstracto.core.command.exception.AbstractoTemplatedException;
import dev.sheldan.abstracto.core.command.execution.UnparsedCommandParameterPiece;
import dev.sheldan.abstracto.core.command.handler.provided.TextChannelParameterHandler;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.TextChannel;
import org.apache.commons.lang3.math.NumberUtils;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.regex.Matcher;
@Component
@@ -23,8 +26,19 @@ public class TextChannelParameterHandlerImpl implements TextChannelParameterHand
if(matcher.matches()) {
return iterators.getChannelIterator().next();
} else {
long channelId = Long.parseLong(inputString);
return context.getGuild().getTextChannelById(channelId);
if(NumberUtils.isParsable(inputString)) {
long channelId = Long.parseLong(inputString);
return context.getGuild().getTextChannelById(channelId);
} else {
List<TextChannel> possibleTextChannels = context.getGuild().getTextChannelsByName(inputString, true);
if(possibleTextChannels.isEmpty()) {
throw new AbstractoTemplatedException("No channel found with name.", "no_channel_found_by_name_exception");
}
if(possibleTextChannels.size() > 1) {
throw new AbstractoTemplatedException("Multiple channels found with name.", "multiple_channels_found_by_name_exception");
}
return possibleTextChannels.get(0);
}
}
}

View File

@@ -41,25 +41,30 @@ public class ExceptionServiceBean implements ExceptionService {
@Override
public CommandResult reportExceptionToContext(Throwable throwable, CommandContext context, Command command) {
if(command != null && command.getConfiguration().isSupportsEmbedException()) {
if(command != null) {
log.info("Reporting generic exception {} of command {} towards channel {} in server {}.",
throwable.getClass().getSimpleName(), command.getConfiguration().getName(), context.getChannel().getId(), context.getGuild().getId());
} else {
log.info("Reporting generic exception {} towards channel {} in server {}.",
throwable.getClass().getSimpleName(), context.getChannel().getId(), context.getGuild().getId());
}
if((command != null && command.getConfiguration().isSupportsEmbedException()) || throwable instanceof Templatable) {
try {
GenericExceptionModel exceptionModel = buildCommandModel(throwable, context);
log.info("Reporting generic exception {} of command {} towards channel {} in server {}.",
throwable.getClass().getSimpleName(), command.getConfiguration().getName(), context.getChannel().getId(), context.getGuild().getId());
channelService.sendEmbedTemplateInTextChannelList("generic_command_exception", exceptionModel, context.getChannel());
reportGenericException(throwable, context);
} catch (Exception e) {
log.error("Failed to notify about exception.", e);
}
} else if(throwable instanceof Templatable){
GenericExceptionModel exceptionModel = buildCommandModel(throwable, context);
String text = templateService.renderTemplate(MODEL_WRAPPER_TEMPLATE_KEY, exceptionModel, context.getGuild().getIdLong());
channelService.sendTextToChannel(text, context.getChannel());
} else {
channelService.sendTextToChannel(throwable.getLocalizedMessage(), context.getChannel());
}
return CommandResult.fromReportedError();
}
private void reportGenericException(Throwable throwable, CommandContext context) {
GenericExceptionModel exceptionModel = buildCommandModel(throwable, context);
channelService.sendEmbedTemplateInTextChannelList("generic_command_exception", exceptionModel, context.getChannel());
}
@Override
public void reportExceptionToGuildMessageReceivedContext(Throwable exception, GuildMessageReceivedEvent event) {
if(exception instanceof Templatable){

View File

@@ -225,9 +225,9 @@ public class ReactionServiceBean implements ReactionService {
public CompletableFuture<Void> removeReaction(CachedMessage message, CachedEmote cachedEmote, ServerUser user) {
CompletableFuture<Message> messageFuture = messageService.loadMessageFromCachedMessage(message);
CompletableFuture<Member> memberFuture = memberService.retrieveMemberInServer(user);
return FutureUtils.toSingleFuture(Arrays.asList(messageFuture, memberFuture)).thenCompose(unused -> {
return removeReaction(messageFuture.join(), cachedEmote, memberFuture.join().getUser());
});
return FutureUtils.toSingleFuture(Arrays.asList(messageFuture, memberFuture)).thenCompose(unused ->
removeReaction(messageFuture.join(), cachedEmote, memberFuture.join().getUser())
);
}
@Override

View File

@@ -88,9 +88,9 @@ public class StartupServiceBean implements Startup {
Set<Long> knownRolesId = SnowflakeUtils.getOwnItemsIds(knownARoles);
Set<Long> availableRoles = SnowflakeUtils.getSnowflakeIds(existingRoles);
Set<Long> newRoles = SetUtils.difference(availableRoles, knownRolesId);
newRoles.forEach(aLong -> {
roleManagementService.createRole(aLong, existingAServer);
});
newRoles.forEach(aLong ->
roleManagementService.createRole(aLong, existingAServer)
);
}
private void synchronizeChannelsOf(Guild guild, AServer existingServer){

View File

@@ -286,7 +286,7 @@ public class TemplateServiceBean implements TemplateService {
public String renderSimpleTemplate(String key, Long serverId) {
try {
serverContext.setServerId(serverId);
return renderSimpleTemplate(key, serverId);
return renderSimpleTemplate(key);
} finally {
serverContext.clear();
}

View File

@@ -1,5 +1,6 @@
package dev.sheldan.abstracto.core.command.handler;
import dev.sheldan.abstracto.core.command.exception.AbstractoTemplatedException;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.Message;
@@ -12,6 +13,7 @@ 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.concurrent.CompletableFuture;
@@ -54,7 +56,7 @@ public class MemberParameterHandlerImplTest extends AbstractParameterHandlerTest
oneMemberInIterator();
String input = getUserMention();
CompletableFuture<Member> parsed = (CompletableFuture) testUnit.handleAsync(getPieceWithValue(input), iterators, Member.class, null);
Assert.assertEquals(parsed.join(), member);
Assert.assertEquals(member, parsed.join());
}
@Test
@@ -63,13 +65,35 @@ public class MemberParameterHandlerImplTest extends AbstractParameterHandlerTest
setupMessage();
String input = USER_ID.toString();
CompletableFuture<Member> parsed = (CompletableFuture) testUnit.handleAsync(getPieceWithValue(input), null, Member.class, message);
Assert.assertEquals(parsed.join(), member);
Assert.assertEquals(member, parsed.join());
}
@Test(expected = NumberFormatException.class)
public void testInvalidMemberMention() {
@Test(expected = AbstractoTemplatedException.class)
public void testNotExistingMember() {
String input = "test";
testUnit.handleAsync(getPieceWithValue(input), null, Member.class, null);
when(message.getGuild()).thenReturn(guild);
when(guild.getMembersByName(input, true)).thenReturn(new ArrayList<>());
testUnit.handleAsync(getPieceWithValue(input), null, Member.class, message);
}
@Test(expected = AbstractoTemplatedException.class)
public void testMultipleFoundMemberByName() {
String input = "test";
Member secondMember = Mockito.mock(Member.class);
when(message.getGuild()).thenReturn(guild);
when(guild.getMembersByName(input, true)).thenReturn(Arrays.asList(member, secondMember));
testUnit.handleAsync(getPieceWithValue(input), null, Member.class, message);
}
@Test
public void testFindMemberByName() {
String input = "test";
when(message.getGuild()).thenReturn(guild);
when(guild.getMembersByName(input, true)).thenReturn(Arrays.asList(member));
CompletableFuture<Object> future = testUnit.handleAsync(getPieceWithValue(input), null, Member.class, message);
Member returnedMember = (Member) future.join();
Assert.assertFalse(future.isCompletedExceptionally());
Assert.assertEquals(member, returnedMember);
}
private String getUserMention() {

View File

@@ -1,5 +1,6 @@
package dev.sheldan.abstracto.core.command.handler;
import dev.sheldan.abstracto.core.command.exception.AbstractoTemplatedException;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.Role;
@@ -8,8 +9,10 @@ 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;
@@ -50,7 +53,7 @@ public class RoleParameterHandlerImplTest extends AbstractParameterHandlerTest {
oneRoleIterator();
String input = getRoleMention();
Role parsed = (Role) testUnit.handle(getPieceWithValue(input), iterators, Role.class, null);
Assert.assertEquals(parsed, role);
Assert.assertEquals(role, parsed);
}
@Test
@@ -58,13 +61,33 @@ public class RoleParameterHandlerImplTest extends AbstractParameterHandlerTest {
setupMessage();
String input = ROLE_ID.toString();
Role parsed = (Role) testUnit.handle(getPieceWithValue(input), null, Role.class, message);
Assert.assertEquals(parsed, role);
Assert.assertEquals(role, parsed);
}
@Test(expected = NumberFormatException.class)
@Test(expected = AbstractoTemplatedException.class)
public void testInvalidRoleMention() {
String input = "test";
testUnit.handle(getPieceWithValue(input), null, Role.class, null);
when(message.getGuild()).thenReturn(guild);
when(guild.getRolesByName(input, true)).thenReturn(new ArrayList<>());
testUnit.handle(getPieceWithValue(input), null, Role.class, message);
}
@Test(expected = AbstractoTemplatedException.class)
public void testMultipleRolesFoundByName() {
String input = "test";
Role secondRole = Mockito.mock(Role.class);
when(message.getGuild()).thenReturn(guild);
when(guild.getRolesByName(input, true)).thenReturn(Arrays.asList(role, secondRole));
testUnit.handle(getPieceWithValue(input), null, Role.class, message);
}
@Test
public void testFindRoleByName() {
String input = "test";
when(message.getGuild()).thenReturn(guild);
when(guild.getRolesByName(input, true)).thenReturn(Arrays.asList(role));
Role returnedRole = (Role) testUnit.handle(getPieceWithValue(input), null, Role.class, message);
Assert.assertEquals(role, returnedRole);
}
private String getRoleMention() {

View File

@@ -1,5 +1,6 @@
package dev.sheldan.abstracto.core.command.handler;
import dev.sheldan.abstracto.core.command.exception.AbstractoTemplatedException;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.TextChannel;
@@ -8,8 +9,10 @@ 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;
@@ -50,7 +53,7 @@ public class TextChannelParameterHandlerImplTest extends AbstractParameterHandle
oneChannelInIterator();
String input = getChannelMention();
TextChannel parsed = (TextChannel) testUnit.handle(getPieceWithValue(input), iterators, TextChannel.class, null);
Assert.assertEquals(parsed, channel);
Assert.assertEquals(channel, parsed);
}
@Test
@@ -58,15 +61,36 @@ public class TextChannelParameterHandlerImplTest extends AbstractParameterHandle
setupMessage();
String input = CHANNEL_ID.toString();
TextChannel parsed = (TextChannel) testUnit.handle(getPieceWithValue(input), null, TextChannel.class, message);
Assert.assertEquals(parsed, channel);
Assert.assertEquals(channel, parsed);
}
@Test(expected = NumberFormatException.class)
public void testInvalidChannelMention() {
@Test(expected = AbstractoTemplatedException.class)
public void testInvalidChannelName() {
String input = "test";
testUnit.handle(getPieceWithValue(input), null, TextChannel.class, null);
when(message.getGuild()).thenReturn(guild);
when(guild.getTextChannelsByName(input, true)).thenReturn(new ArrayList<>());
testUnit.handle(getPieceWithValue(input), null, TextChannel.class, message);
}
@Test(expected = AbstractoTemplatedException.class)
public void testFoundMultipleChannelsByName() {
String input = "test";
TextChannel secondChannel = Mockito.mock(TextChannel.class);
when(message.getGuild()).thenReturn(guild);
when(guild.getTextChannelsByName(input, true)).thenReturn(Arrays.asList(channel, secondChannel));
testUnit.handle(getPieceWithValue(input), null, TextChannel.class, message);
}
@Test
public void testFindChannelByName() {
String input = "test";
when(message.getGuild()).thenReturn(guild);
when(guild.getTextChannelsByName(input, true)).thenReturn(Arrays.asList(channel));
TextChannel returnedChannel = (TextChannel) testUnit.handle(getPieceWithValue(input), null, TextChannel.class, message);
Assert.assertEquals(channel, returnedChannel);
}
private String getChannelMention() {
return String.format("<#%d>", CHANNEL_ID);
}

View File

@@ -26,7 +26,7 @@ public class SchedulerStartupService {
@EventListener
@Transactional(isolation = Isolation.SERIALIZABLE)
public void handleContextRefreshEvent(ContextRefreshedEvent ctxStartEvt) {
schedulerJobManagementServiceBean.findAll().forEach((schedulerJob) -> {
schedulerJobManagementServiceBean.findAll().forEach(schedulerJob -> {
if(!schedulerJobManagementServiceBean.doesJobExist(schedulerJob) || !schedulerJobManagementServiceBean.isJobDefinitionTheSame(schedulerJob)) {
schedulerJobManagementServiceBean.createOrUpdate(schedulerJob);
}