reworked exception handling, different exceptions whether or why it failed, all of which are unchecked

added feature flags for commands/listeners
added enable/disable command
added feature flag handling to command received handler
added boolean parameter support
fixed 1 parameter commands
fixed posttargets not working on multiple servers, removed unique constraint on posttarget names
added setup validation to suggestions
added quartz property loader
moved join/leave logger to moderation
reworked the way the message listener are handled (separate listener around)
This commit is contained in:
Sheldan
2020-04-04 12:55:01 +02:00
parent c9557fccc2
commit bf94af66d5
132 changed files with 1378 additions and 530 deletions

View File

@@ -1,11 +1,11 @@
package dev.sheldan.abstracto.moderation.command;
import dev.sheldan.abstracto.command.Command;
import dev.sheldan.abstracto.command.AbstractFeatureFlaggedCommand;
import dev.sheldan.abstracto.command.HelpInfo;
import dev.sheldan.abstracto.command.execution.*;
import dev.sheldan.abstracto.moderation.Moderation;
import dev.sheldan.abstracto.moderation.config.ModerationFeatures;
import dev.sheldan.abstracto.moderation.models.template.BanLog;
import dev.sheldan.abstracto.moderation.models.template.WarnLog;
import dev.sheldan.abstracto.moderation.service.BanService;
import dev.sheldan.abstracto.templating.TemplateService;
import lombok.extern.slf4j.Slf4j;
@@ -18,7 +18,7 @@ import java.util.List;
@Component
@Slf4j
public class Ban implements Command {
public class Ban extends AbstractFeatureFlaggedCommand {
@Autowired
private BanService banService;
@@ -27,7 +27,7 @@ public class Ban implements Command {
private TemplateService templateService;
@Override
public Result execute(CommandContext commandContext) {
public CommandResult execute(CommandContext commandContext) {
List<Object> parameters = commandContext.getParameters().getParameters();
Member member = (Member) parameters.get(0);
String defaultReason = templateService.renderTemplate("ban_default_reason", null);
@@ -38,7 +38,7 @@ public class Ban implements Command {
banLogModel.setBanningUser(commandContext.getAuthor());
banLogModel.setReason(reason);
banService.banMember(member, reason, banLogModel);
return Result.fromSuccess();
return CommandResult.fromSuccess();
}
@Override
@@ -56,4 +56,9 @@ public class Ban implements Command {
.help(helpInfo)
.build();
}
@Override
public String getFeature() {
return ModerationFeatures.MODERATION;
}
}

View File

@@ -1,19 +1,21 @@
package dev.sheldan.abstracto.moderation.command;
import dev.sheldan.abstracto.command.Command;
import dev.sheldan.abstracto.command.AbstractFeatureFlaggedCommand;
import dev.sheldan.abstracto.command.HelpInfo;
import dev.sheldan.abstracto.command.execution.*;
import dev.sheldan.abstracto.core.models.UserInitiatedServerContext;
import dev.sheldan.abstracto.moderation.Moderation;
import dev.sheldan.abstracto.moderation.config.ModerationFeatures;
import dev.sheldan.abstracto.moderation.models.template.BanIdLog;
import dev.sheldan.abstracto.moderation.service.BanService;
import dev.sheldan.abstracto.templating.TemplateService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
public class BanId implements Command {
@Component
public class BanId extends AbstractFeatureFlaggedCommand {
@Autowired
private TemplateService templateService;
@@ -22,7 +24,7 @@ public class BanId implements Command {
private BanService banService;
@Override
public Result execute(CommandContext commandContext) {
public CommandResult execute(CommandContext commandContext) {
List<Object> parameters = commandContext.getParameters().getParameters();
Long userId = (Long) parameters.get(0);
String defaultReason = templateService.renderTemplate("ban_default_reason", null);
@@ -33,7 +35,7 @@ public class BanId implements Command {
banLogModel.setReason(reason);
banService.banMember(userId, commandContext.getGuild().getIdLong(), reason, banLogModel);
return Result.fromSuccess();
return CommandResult.fromSuccess();
}
@Override
@@ -51,4 +53,9 @@ public class BanId implements Command {
.help(helpInfo)
.build();
}
@Override
public String getFeature() {
return ModerationFeatures.MODERATION;
}
}

View File

@@ -1,10 +1,10 @@
package dev.sheldan.abstracto.moderation.command;
import dev.sheldan.abstracto.command.Command;
import dev.sheldan.abstracto.command.AbstractFeatureFlaggedCommand;
import dev.sheldan.abstracto.command.HelpInfo;
import dev.sheldan.abstracto.command.execution.*;
import dev.sheldan.abstracto.moderation.Moderation;
import dev.sheldan.abstracto.moderation.models.template.BanIdLog;
import dev.sheldan.abstracto.moderation.config.ModerationFeatures;
import dev.sheldan.abstracto.moderation.models.template.KickLogModel;
import dev.sheldan.abstracto.moderation.service.KickServiceBean;
import dev.sheldan.abstracto.templating.TemplateService;
@@ -16,15 +16,16 @@ import java.util.ArrayList;
import java.util.List;
@Component
public class Kick implements Command {
public class Kick extends AbstractFeatureFlaggedCommand {
@Autowired
private TemplateService templateService;
@Autowired
private KickServiceBean kickService;
@Override
public Result execute(CommandContext commandContext) {
public CommandResult execute(CommandContext commandContext) {
List<Object> parameters = commandContext.getParameters().getParameters();
Member member = (Member) parameters.get(0);
@@ -36,7 +37,7 @@ public class Kick implements Command {
kickLogModel.setKickingUser(commandContext.getAuthor());
kickLogModel.setReason(reason);
kickService.kickMember(member, reason, kickLogModel);
return Result.fromSuccess();
return CommandResult.fromSuccess();
}
@Override
@@ -54,4 +55,9 @@ public class Kick implements Command {
.help(helpInfo)
.build();
}
@Override
public String getFeature() {
return ModerationFeatures.MODERATION;
}
}

View File

@@ -1,12 +1,13 @@
package dev.sheldan.abstracto.moderation.command;
import dev.sheldan.abstracto.command.Command;
import dev.sheldan.abstracto.command.HelpInfo;
import dev.sheldan.abstracto.command.*;
import dev.sheldan.abstracto.command.execution.CommandConfiguration;
import dev.sheldan.abstracto.command.execution.CommandContext;
import dev.sheldan.abstracto.command.execution.Parameter;
import dev.sheldan.abstracto.command.execution.Result;
import dev.sheldan.abstracto.command.execution.CommandResult;
import dev.sheldan.abstracto.core.service.Bot;
import dev.sheldan.abstracto.moderation.Moderation;
import dev.sheldan.abstracto.moderation.config.ModerationFeatures;
import dev.sheldan.abstracto.moderation.service.SlowModeService;
import net.dv8tion.jda.api.entities.TextChannel;
import org.springframework.beans.factory.annotation.Autowired;
@@ -17,25 +18,22 @@ import java.util.ArrayList;
import java.util.List;
@Component
public class SlowMode implements Command {
public class SlowMode extends AbstractFeatureFlaggedCommand {
@Autowired
private SlowModeService slowModeService;
@Override
public Result execute(CommandContext commandContext) {
public CommandResult execute(CommandContext commandContext) {
TextChannel channel;
long seconds = (Long) commandContext.getParameters().getParameters().get(0);
if(commandContext.getParameters().getParameters().size() == 2) {
channel = (TextChannel) commandContext.getParameters().getParameters().get(1);
if(commandContext.getGuild().getGuildChannelById(channel.getIdLong()) == null) {
throw new IllegalArgumentException("Given channel was not part of the current guild.");
}
} else {
channel = commandContext.getChannel();
}
slowModeService.setSlowMode(channel, Duration.ofSeconds(seconds));
return Result.fromSuccess();
return CommandResult.fromSuccess();
}
@Override
@@ -53,4 +51,9 @@ public class SlowMode implements Command {
.help(helpInfo)
.build();
}
@Override
public String getFeature() {
return ModerationFeatures.MODERATION;
}
}

View File

@@ -1,12 +1,13 @@
package dev.sheldan.abstracto.moderation.command;
import dev.sheldan.abstracto.command.AbstractFeatureFlaggedCommand;
import dev.sheldan.abstracto.command.HelpInfo;
import dev.sheldan.abstracto.command.execution.*;
import dev.sheldan.abstracto.core.service.management.UserManagementService;
import dev.sheldan.abstracto.moderation.Moderation;
import dev.sheldan.abstracto.moderation.config.ModerationFeatures;
import dev.sheldan.abstracto.moderation.models.template.WarnLog;
import dev.sheldan.abstracto.moderation.service.WarnService;
import dev.sheldan.abstracto.command.Command;
import dev.sheldan.abstracto.command.HelpInfo;
import dev.sheldan.abstracto.core.management.UserManagementService;
import dev.sheldan.abstracto.templating.TemplateService;
import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.entities.Member;
@@ -18,7 +19,7 @@ import java.util.List;
@Component
@Slf4j
public class Warn implements Command {
public class Warn extends AbstractFeatureFlaggedCommand {
@Autowired
private UserManagementService userManagementService;
@@ -30,7 +31,7 @@ public class Warn implements Command {
private TemplateService templateService;
@Override
public Result execute(CommandContext commandContext) {
public CommandResult execute(CommandContext commandContext) {
List<Object> parameters = commandContext.getParameters().getParameters();
Member member = (Member) parameters.get(0);
String defaultReason = templateService.renderTemplate("warn_default_reason", null);
@@ -41,7 +42,7 @@ public class Warn implements Command {
warnLogModel.setReason(reason);
warnLogModel.setWarningUser(commandContext.getAuthor());
warnService.warnUser(member, commandContext.getAuthor(), reason, warnLogModel);
return Result.fromSuccess();
return CommandResult.fromSuccess();
}
@Override
@@ -59,4 +60,9 @@ public class Warn implements Command {
.help(helpInfo)
.build();
}
@Override
public String getFeature() {
return ModerationFeatures.WARNINGS;
}
}

View File

@@ -0,0 +1,7 @@
package dev.sheldan.abstracto.moderation.config;
public class ModerationFeatures {
public static String MODERATION = "moderation";
public static String WARNINGS = "warnings";
public static String LOGGING = "logging";
}

View File

@@ -0,0 +1,54 @@
package dev.sheldan.abstracto.moderation.listener;
import dev.sheldan.abstracto.core.listener.JoinListener;
import dev.sheldan.abstracto.core.service.PostTargetService;
import dev.sheldan.abstracto.core.service.management.ServerManagementService;
import dev.sheldan.abstracto.moderation.config.ModerationFeatures;
import dev.sheldan.abstracto.templating.TemplateService;
import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.entities.Guild;
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 javax.annotation.Nonnull;
import java.util.HashMap;
@Service
@Slf4j
public class JoinLogger implements JoinListener {
private static final String USER_JOIN_TEMPLATE = "user_join";
private static final String JOIN_LOG_TARGET = "joinLog";
@Autowired
private ServerManagementService serverManagementService;
@Autowired
private TemplateService templateService;
@Autowired
private PostTargetService postTargetService;
@NotNull
private HashMap<String, Object> getUserParameter(@Nonnull User user) {
HashMap<String, Object> parameters = new HashMap<>();
parameters.put("user", user);
return parameters;
}
@Override
public void execute(Member member, Guild guild) {
HashMap<String, Object> parameters = getUserParameter(member.getUser());
String text = templateService.renderTemplate(USER_JOIN_TEMPLATE, parameters);;
postTargetService.sendTextInPostTarget(text, JOIN_LOG_TARGET, guild.getIdLong());
}
@Override
public String getFeature() {
return ModerationFeatures.LOGGING;
}
}

View File

@@ -0,0 +1,54 @@
package dev.sheldan.abstracto.moderation.listener;
import dev.sheldan.abstracto.core.listener.LeaveListener;
import dev.sheldan.abstracto.core.service.PostTargetService;
import dev.sheldan.abstracto.core.service.management.ServerManagementService;
import dev.sheldan.abstracto.moderation.config.ModerationFeatures;
import dev.sheldan.abstracto.templating.TemplateService;
import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.entities.Guild;
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 javax.annotation.Nonnull;
import java.util.HashMap;
@Service
@Slf4j
public class LeaveLogger implements LeaveListener {
private static final String USER_LEAVE_TEMPLATE = "user_leave";
private static final String LEAVE_LOG_TARGET = "leaveLog";
@Autowired
private ServerManagementService serverManagementService;
@Autowired
private TemplateService templateService;
@Autowired
private PostTargetService postTargetService;
@NotNull
private HashMap<String, Object> getUserParameter(@Nonnull User user) {
HashMap<String, Object> parameters = new HashMap<>();
parameters.put("user", user);
parameters.put("userMention", user.getAsMention());
return parameters;
}
@Override
public void execute(Member member, Guild guild) {
String text = templateService.renderTemplate(USER_LEAVE_TEMPLATE, getUserParameter(member.getUser()));
postTargetService.sendTextInPostTarget(text, LEAVE_LOG_TARGET, guild.getIdLong());
}
@Override
public String getFeature() {
return ModerationFeatures.LOGGING;
}
}

View File

@@ -2,12 +2,13 @@ package dev.sheldan.abstracto.moderation.listener;
import dev.sheldan.abstracto.core.listener.MessageDeletedListener;
import dev.sheldan.abstracto.core.models.CachedMessage;
import dev.sheldan.abstracto.core.utils.ContextUtils;
import dev.sheldan.abstracto.core.models.embed.MessageToSend;
import dev.sheldan.abstracto.core.service.MessageCache;
import dev.sheldan.abstracto.core.service.PostTargetService;
import dev.sheldan.abstracto.core.utils.ContextUtils;
import dev.sheldan.abstracto.moderation.config.ModerationFeatures;
import dev.sheldan.abstracto.moderation.models.template.listener.MessageDeletedAttachmentLog;
import dev.sheldan.abstracto.moderation.models.template.listener.MessageDeletedLog;
import dev.sheldan.abstracto.core.models.embed.MessageToSend;
import dev.sheldan.abstracto.templating.TemplateService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
@@ -49,4 +50,9 @@ public class MessageDeleteLogListener implements MessageDeletedListener {
postTargetService.sendEmbedInPostTarget(attachmentEmbed, DELETE_LOG_TARGET, messageFromCache.getServerId());
}
}
@Override
public String getFeature() {
return ModerationFeatures.LOGGING;
}
}

View File

@@ -5,6 +5,7 @@ import dev.sheldan.abstracto.core.models.CachedMessage;
import dev.sheldan.abstracto.core.models.embed.MessageToSend;
import dev.sheldan.abstracto.core.service.MessageCache;
import dev.sheldan.abstracto.core.service.PostTargetService;
import dev.sheldan.abstracto.moderation.config.ModerationFeatures;
import dev.sheldan.abstracto.moderation.models.template.listener.MessageEditedLog;
import dev.sheldan.abstracto.templating.TemplateService;
import lombok.extern.slf4j.Slf4j;
@@ -40,13 +41,17 @@ public class MessageEditedListener implements MessageTextUpdatedListener {
builder().
messageAfter(messageAfter)
.messageBefore(messageBefore)
.textChannel(messageAfter.getTextChannel())
.messageChannel(messageAfter.getTextChannel())
.guild(messageAfter.getGuild())
.member(messageAfter.getMember()).build();
String simpleMessageUpdatedMessage = templateService.renderTemplate(MESSAGE_EDITED_TEMPLATE, log);
postTargetService.sendTextInPostTarget(simpleMessageUpdatedMessage, EDIT_LOG_TARGET, messageAfter.getGuild().getIdLong());
MessageToSend message = templateService.renderEmbedTemplate(MESSAGE_EDITED_TEMPLATE, log);
postTargetService.sendEmbedInPostTarget(message, EDIT_LOG_TARGET, messageBefore.getServerId());
}
@Override
public String getFeature() {
return ModerationFeatures.LOGGING;
}
}

View File

@@ -1,6 +1,6 @@
package dev.sheldan.abstracto.moderation.service;
import dev.sheldan.abstracto.core.exception.NotFoundException;
import dev.sheldan.abstracto.core.exception.GuildException;
import dev.sheldan.abstracto.core.models.ServerContext;
import dev.sheldan.abstracto.core.service.Bot;
import dev.sheldan.abstracto.core.service.PostTargetService;
@@ -50,7 +50,7 @@ public class BanServiceBean implements BanService {
guildByIdOptional.get().ban(userId.toString(), 0, reason).queue();
} else {
log.warn("Guild {} not found. Not able to ban user {}", guildId, userId);
throw new NotFoundException(String.format("Guild %s not found. Not able to ban user %s", guildId, userId));
throw new GuildException(String.format("Guild %s not found. Not able to ban user %s", guildId, userId));
}
}
}

View File

@@ -1,6 +1,7 @@
package dev.sheldan.abstracto.moderation.service;
import dev.sheldan.abstracto.core.exception.NotFoundException;
import dev.sheldan.abstracto.core.exception.ChannelException;
import dev.sheldan.abstracto.core.exception.GuildException;
import dev.sheldan.abstracto.core.service.Bot;
import dev.sheldan.abstracto.core.service.PostTargetService;
import dev.sheldan.abstracto.moderation.models.template.KickLogModel;
@@ -36,7 +37,7 @@ public class KickServiceBean implements KickService {
this.sendKickLog(kickLogModel);
} else {
log.warn("Not able to kick. Guild {} not found.", kickLogModel.getGuild().getIdLong());
throw new NotFoundException(String.format("Not able to kick %s. Guild %s not found", kickLogModel.getMember().getIdLong(), kickLogModel.getGuild().getIdLong()));
throw new GuildException(String.format("Not able to kick %s. Guild %s not found", kickLogModel.getMember().getIdLong(), kickLogModel.getGuild().getIdLong()));
}
}

View File

@@ -1,6 +1,6 @@
package dev.sheldan.abstracto.moderation.service;
import dev.sheldan.abstracto.core.exception.NotFoundException;
import dev.sheldan.abstracto.core.exception.ChannelException;
import dev.sheldan.abstracto.core.models.database.AChannel;
import dev.sheldan.abstracto.core.service.Bot;
import lombok.extern.slf4j.Slf4j;
@@ -34,7 +34,7 @@ public class SlowModeServiceBean implements SlowModeService {
TextChannel textChannel = textChannelOptional.get();
this.setSlowMode(textChannel, duration);
} else {
throw new NotFoundException(String.format("Channel %s not found in guild %s", channel.getId(), channel.getServer().getId()));
throw new ChannelException(String.format("Channel %s not found in guild %s", channel.getId(), channel.getServer().getId()));
}
}
}

View File

@@ -1,5 +1,6 @@
package dev.sheldan.abstracto.moderation.service;
import dev.sheldan.abstracto.core.exception.UserException;
import dev.sheldan.abstracto.core.models.ServerContext;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.core.models.database.AUser;
@@ -8,8 +9,8 @@ import dev.sheldan.abstracto.moderation.models.template.WarnLog;
import dev.sheldan.abstracto.moderation.models.template.WarnNotification;
import dev.sheldan.abstracto.moderation.models.Warning;
import dev.sheldan.abstracto.moderation.service.management.WarnManagementService;
import dev.sheldan.abstracto.core.management.ServerManagementService;
import dev.sheldan.abstracto.core.management.UserManagementService;
import dev.sheldan.abstracto.core.service.management.ServerManagementService;
import dev.sheldan.abstracto.core.service.management.UserManagementService;
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
import dev.sheldan.abstracto.core.service.Bot;
import dev.sheldan.abstracto.core.service.PostTargetService;
@@ -18,11 +19,13 @@ import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.JDA;
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.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
@Slf4j
@Component
@@ -64,18 +67,27 @@ public class WarnServiceBean implements WarnService {
if(guildById.isPresent()) {
guildName = guildById.get().getName();
}
warnLog.setWarning(warning);
this.sendWarnLog(warnLog);
WarnNotification warnNotification = WarnNotification.builder().warning(warning).serverName(guildName).build();
if(userBeingWarned != null) {
String warnLogMessage = templateService.renderTemplate(WARN_NOTIFICATION_TEMPLATE, warnNotification);
CompletableFuture<Message> messageFuture = new CompletableFuture<>();
// TODO the person executing this, is unaware that the message failed
userBeingWarned.openPrivateChannel().queue(privateChannel -> {
log.info("Messaging user {} about warn {}", warnedAUser.getId(), warning.getId());
privateChannel.sendMessage(warnLogMessage).queue();
privateChannel.sendMessage(warnLogMessage).queue(messageFuture::complete, messageFuture::completeExceptionally);
});
messageFuture.exceptionally(e -> {
log.warn("Failed to send message. ", e);
return null;
});
} else {
log.warn("Unable to find user {} in guild {} to warn.", warnedAUser.getId(), serverOfWarning.getId());
throw new UserException(String.format("Unable to find user %s.", warnedAUser.getId()));
}
warnLog.setWarning(warning);
this.sendWarnLog(warnLog);
}
@Override

View File

@@ -1 +1,4 @@
abstracto.postTargets.moderation=joinLog,leaveLog,warnLog,kickLog,banLog,editLog,deleteLog
abstracto.features.moderation=false
abstracto.features.warnings=false
abstracto.features.logging=true

View File

@@ -3,7 +3,7 @@
"name": "${member.effectiveName}#${member.user.discriminator}",
"avatar": "${member.user.effectiveAvatarUrl}"
},
"description": "Message from ${member.effectiveName}#${member.user.discriminator} (${member.idLong?c}) removed in ${textChannel.asMention}",
"description": "Message from ${member.effectiveName}#${member.user.discriminator} (${member.idLong?c}) removed in ${messageChannel.asMention}",
"color" : {
"r": 200,
"g": 0,
@@ -16,7 +16,7 @@
},
{
"name": "Link",
"value": "[${textChannel.name}](${message.messageUrl})"
"value": "[${messageChannel.name}](${message.messageUrl})"
}
]
}

View File

@@ -1,2 +1,2 @@
Message from ${member.effectiveName} (${member.idLong?c}) deleted in ${textChannel.asMention}.
Message from ${member.effectiveName} (${member.idLong?c}) deleted in ${messageChannel.asMention}.
Message: ${message.content}

View File

@@ -3,7 +3,7 @@
"name": "${member.effectiveName}#${member.user.discriminator}",
"avatar": "${member.user.effectiveAvatarUrl}"
},
"description": "Message from ${member.effectiveName}#${member.user.discriminator} (${member.idLong?c}) edited in ${textChannel.asMention}",
"description": "Message from ${member.effectiveName}#${member.user.discriminator} (${member.idLong?c}) edited in ${messageChannel.asMention}",
"color" : {
"r": 200,
"g": 0,
@@ -12,7 +12,7 @@
"fields": [
{
"name": "Original Message: ",
"value": "${messageBefore.contentRaw}"
"value": "${messageBefore.content}"
},
{
"name": "New Message: ",
@@ -20,7 +20,7 @@
},
{
"name": "Jump link",
"value": "[${textChannel.name}](${messageBefore.jumpUrl})"
"value": "[${messageChannel.name}](${messageBefore.messageUrl})"
}
]
}

View File

@@ -1,3 +1,3 @@
Message from ${member.effectiveName} (${member.idLong?c}) edited in ${textChannel.asMention}.
Before: ${messageBefore.contentRaw}
Message from ${member.effectiveName} (${member.idLong?c}) edited in ${messageChannel.asMention}.
Before: ${messageBefore.content}
After: ${messageAfter.contentRaw}

View File

@@ -25,7 +25,7 @@
<#if warning?has_content>
{
"name": "Location of the incident",
"value": "[${textChannel.name}](${message.jumpUrl})"
"value": "[${messageChannel.name}](${message.jumpUrl})"
},
</#if>
{

View File

@@ -1,10 +1,10 @@
package dev.sheldan.abstracto.utility.command;
import dev.sheldan.abstracto.command.Command;
import dev.sheldan.abstracto.command.HelpInfo;
import dev.sheldan.abstracto.command.*;
import dev.sheldan.abstracto.command.execution.*;
import dev.sheldan.abstracto.templating.TemplateService;
import dev.sheldan.abstracto.utility.Utility;
import dev.sheldan.abstracto.utility.config.UtilityFeatures;
import dev.sheldan.abstracto.utility.models.template.ShowEmoteLog;
import net.dv8tion.jda.api.entities.Emote;
import org.springframework.beans.factory.annotation.Autowired;
@@ -14,7 +14,7 @@ import java.util.ArrayList;
import java.util.List;
@Component
public class ShowEmote implements Command {
public class ShowEmote extends AbstractFeatureFlaggedCommand {
private static final String SHOW_EMOTE_RESPONSE_TEMPLATE = "showEmote_response";
@@ -22,18 +22,18 @@ public class ShowEmote implements Command {
private TemplateService templateService;
@Override
public Result execute(CommandContext commandContext) {
public CommandResult execute(CommandContext commandContext) {
List<Object> parameters = commandContext.getParameters().getParameters();
Object emoteParameter = parameters.get(0);
if(!(emoteParameter instanceof Emote)) {
return Result.fromError("No custom emote found.");
return CommandResult.fromError("No custom emote found.");
}
Emote emote = (Emote) emoteParameter;
ShowEmoteLog emoteLog = (ShowEmoteLog) ContextConverter.fromCommandContext(commandContext, ShowEmoteLog.class);
emoteLog.setEmote(emote);
String message = templateService.renderTemplate(SHOW_EMOTE_RESPONSE_TEMPLATE, emoteLog);
commandContext.getChannel().sendMessage(message).queue();
return Result.fromSuccess();
return CommandResult.fromSuccess();
}
@Override
@@ -50,4 +50,9 @@ public class ShowEmote implements Command {
.help(helpInfo)
.build();
}
@Override
public String getFeature() {
return UtilityFeatures.UTILITY;
}
}

View File

@@ -1,14 +1,15 @@
package dev.sheldan.abstracto.utility.command;
import dev.sheldan.abstracto.command.Command;
import dev.sheldan.abstracto.command.AbstractFeatureFlaggedCommand;
import dev.sheldan.abstracto.command.HelpInfo;
import dev.sheldan.abstracto.command.execution.CommandConfiguration;
import dev.sheldan.abstracto.command.execution.CommandContext;
import dev.sheldan.abstracto.command.execution.CommandResult;
import dev.sheldan.abstracto.command.execution.Parameter;
import dev.sheldan.abstracto.command.execution.Result;
import dev.sheldan.abstracto.core.models.embed.MessageToSend;
import dev.sheldan.abstracto.templating.TemplateService;
import dev.sheldan.abstracto.utility.Utility;
import dev.sheldan.abstracto.utility.config.UtilityFeatures;
import dev.sheldan.abstracto.utility.models.template.starboard.StarStatsModel;
import dev.sheldan.abstracto.utility.service.StarboardService;
import org.springframework.beans.factory.annotation.Autowired;
@@ -18,7 +19,7 @@ import java.util.ArrayList;
import java.util.List;
@Component
public class StarStats implements Command {
public class StarStats extends AbstractFeatureFlaggedCommand {
public static final String STARSTATS_RESPONSE_TEMPLATE = "starStats_response";
@Autowired
@@ -28,11 +29,11 @@ public class StarStats implements Command {
private TemplateService templateService;
@Override
public Result execute(CommandContext commandContext) {
public CommandResult execute(CommandContext commandContext) {
StarStatsModel result = starboardService.retrieveStarStats(commandContext.getGuild().getIdLong());
MessageToSend messageToSend = templateService.renderEmbedTemplate(STARSTATS_RESPONSE_TEMPLATE, result);
commandContext.getChannel().sendMessage(messageToSend.getEmbed()).queue();
return Result.fromSuccess();
return CommandResult.fromSuccess();
}
@Override
@@ -48,4 +49,9 @@ public class StarStats implements Command {
.help(helpInfo)
.build();
}
@Override
public String getFeature() {
return UtilityFeatures.STARBOARD;
}
}

View File

@@ -1,9 +1,9 @@
package dev.sheldan.abstracto.utility.command.remind;
import dev.sheldan.abstracto.command.Command;
import dev.sheldan.abstracto.command.HelpInfo;
import dev.sheldan.abstracto.command.*;
import dev.sheldan.abstracto.command.execution.*;
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
import dev.sheldan.abstracto.utility.config.UtilityFeatures;
import dev.sheldan.abstracto.utility.Utility;
import dev.sheldan.abstracto.utility.models.template.ReminderModel;
import dev.sheldan.abstracto.utility.service.ReminderService;
@@ -16,13 +16,13 @@ import java.util.ArrayList;
import java.util.List;
@Component
public class Remind implements Command {
public class Remind extends AbstractFeatureFlaggedCommand {
@Autowired
private ReminderService remindService;
@Override
public Result execute(CommandContext commandContext) {
public CommandResult execute(CommandContext commandContext) {
List<Object> parameters = commandContext.getParameters().getParameters();
Duration remindTime = (Duration) parameters.get(0);
String text = (String) parameters.get(1);
@@ -31,7 +31,7 @@ public class Remind implements Command {
remindModel.setMessage(commandContext.getMessage());
remindModel.setRemindText(text);
remindService.createReminderInForUser(aUserInAServer, text, remindTime, remindModel);
return Result.fromSuccess();
return CommandResult.fromSuccess();
}
@Override
@@ -49,4 +49,9 @@ public class Remind implements Command {
.help(helpInfo)
.build();
}
@Override
public String getFeature() {
return UtilityFeatures.REMIND;
}
}

View File

@@ -1,9 +1,10 @@
package dev.sheldan.abstracto.utility.command.suggest;
import dev.sheldan.abstracto.command.Command;
import dev.sheldan.abstracto.command.AbstractFeatureFlaggedCommand;
import dev.sheldan.abstracto.command.HelpInfo;
import dev.sheldan.abstracto.command.execution.*;
import dev.sheldan.abstracto.utility.Utility;
import dev.sheldan.abstracto.utility.config.UtilityFeatures;
import dev.sheldan.abstracto.utility.models.template.SuggestionLog;
import dev.sheldan.abstracto.utility.service.SuggestionService;
import org.springframework.beans.factory.annotation.Autowired;
@@ -13,19 +14,20 @@ import java.util.ArrayList;
import java.util.List;
@Component
public class Accept implements Command {
public class Accept extends AbstractFeatureFlaggedCommand {
@Autowired
private SuggestionService suggestionService;
@Override
public Result execute(CommandContext commandContext) {
public CommandResult execute(CommandContext commandContext) {
suggestionService.validateSetup(commandContext.getGuild().getIdLong());
List<Object> parameters = commandContext.getParameters().getParameters();
Long suggestionId = (Long) parameters.get(0);
String text = parameters.size() == 2 ? (String) parameters.get(1) : "";
SuggestionLog suggestionModel = (SuggestionLog) ContextConverter.fromCommandContext(commandContext, SuggestionLog.class);
suggestionService.acceptSuggestion(suggestionId, text, suggestionModel);
return Result.fromSuccess();
return CommandResult.fromSuccess();
}
@Override
@@ -43,4 +45,9 @@ public class Accept implements Command {
.help(helpInfo)
.build();
}
@Override
public String getFeature() {
return UtilityFeatures.SUGGEST;
}
}

View File

@@ -1,9 +1,10 @@
package dev.sheldan.abstracto.utility.command.suggest;
import dev.sheldan.abstracto.command.Command;
import dev.sheldan.abstracto.command.AbstractFeatureFlaggedCommand;
import dev.sheldan.abstracto.command.HelpInfo;
import dev.sheldan.abstracto.command.execution.*;
import dev.sheldan.abstracto.utility.Utility;
import dev.sheldan.abstracto.utility.config.UtilityFeatures;
import dev.sheldan.abstracto.utility.models.template.SuggestionLog;
import dev.sheldan.abstracto.utility.service.SuggestionService;
import org.springframework.beans.factory.annotation.Autowired;
@@ -13,18 +14,20 @@ import java.util.ArrayList;
import java.util.List;
@Component
public class Reject implements Command {
public class Reject extends AbstractFeatureFlaggedCommand {
@Autowired
private SuggestionService suggestionService;
@Override
public Result execute(CommandContext commandContext) {
public CommandResult execute(CommandContext commandContext) {
suggestionService.validateSetup(commandContext.getGuild().getIdLong());
List<Object> parameters = commandContext.getParameters().getParameters();
Long suggestionId = (Long) parameters.get(0);
String text = parameters.size() == 2 ? (String) parameters.get(1) : "";
SuggestionLog suggestionModel = (SuggestionLog) ContextConverter.fromCommandContext(commandContext, SuggestionLog.class);
suggestionService.rejectSuggestion(suggestionId, text, suggestionModel);
return Result.fromSuccess();
return CommandResult.fromSuccess();
}
@Override
@@ -42,4 +45,9 @@ public class Reject implements Command {
.help(helpInfo)
.build();
}
@Override
public String getFeature() {
return UtilityFeatures.SUGGEST;
}
}

View File

@@ -1,32 +1,33 @@
package dev.sheldan.abstracto.utility.command.suggest;
import dev.sheldan.abstracto.command.Command;
import dev.sheldan.abstracto.command.AbstractFeatureFlaggedCommand;
import dev.sheldan.abstracto.command.HelpInfo;
import dev.sheldan.abstracto.command.execution.*;
import dev.sheldan.abstracto.utility.Utility;
import dev.sheldan.abstracto.utility.config.UtilityFeatures;
import dev.sheldan.abstracto.utility.models.template.SuggestionLog;
import dev.sheldan.abstracto.utility.service.SuggestionService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.List;
@Component
public class Suggest implements Command {
public class Suggest extends AbstractFeatureFlaggedCommand {
@Autowired
private SuggestionService suggestionService;
@Override
public Result execute(CommandContext commandContext) {
public CommandResult execute(CommandContext commandContext) {
suggestionService.validateSetup(commandContext.getGuild().getIdLong());
List<Object> parameters = commandContext.getParameters().getParameters();
String text = (String) parameters.get(0);
SuggestionLog suggestLogModel = (SuggestionLog) ContextConverter.fromCommandContext(commandContext, SuggestionLog.class);
suggestLogModel.setSuggester(commandContext.getAuthor());
suggestionService.createSuggestion(commandContext.getAuthor(), text, suggestLogModel);
return Result.fromSuccess();
return CommandResult.fromSuccess();
}
@Override
@@ -43,4 +44,9 @@ public class Suggest implements Command {
.help(helpInfo)
.build();
}
@Override
public String getFeature() {
return UtilityFeatures.SUGGEST;
}
}

View File

@@ -1,15 +1,11 @@
package dev.sheldan.abstracto.utility.config;
import dev.sheldan.abstracto.core.listener.ServerConfigListener;
import dev.sheldan.abstracto.core.management.ServerManagementService;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.core.management.ConfigManagementService;
import dev.sheldan.abstracto.core.service.management.ConfigManagementService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
@Component
@Slf4j

View File

@@ -0,0 +1,9 @@
package dev.sheldan.abstracto.utility.config;
public class UtilityFeatures {
public static String REMIND = "remind";
public static String STARBOARD = "starboard";
public static String SUGGEST = "suggestion";
public static String UTILITY = "utility";
public static String LINK_EMBEDS = "embeds";
}

View File

@@ -1,8 +1,9 @@
package dev.sheldan.abstracto.listener;
package dev.sheldan.abstracto.utility.listener;
import dev.sheldan.abstracto.core.management.ChannelManagementService;
import dev.sheldan.abstracto.core.management.ServerManagementService;
import dev.sheldan.abstracto.core.management.UserManagementService;
import dev.sheldan.abstracto.core.listener.MessageReceivedListener;
import dev.sheldan.abstracto.core.service.management.ChannelManagementService;
import dev.sheldan.abstracto.core.service.management.ServerManagementService;
import dev.sheldan.abstracto.core.service.management.UserManagementService;
import dev.sheldan.abstracto.core.models.CachedMessage;
import dev.sheldan.abstracto.core.models.database.AChannel;
import dev.sheldan.abstracto.core.models.database.AServer;
@@ -12,12 +13,12 @@ import dev.sheldan.abstracto.core.service.Bot;
import dev.sheldan.abstracto.core.service.MessageCache;
import dev.sheldan.abstracto.core.models.embed.MessageToSend;
import dev.sheldan.abstracto.templating.TemplateService;
import dev.sheldan.abstracto.utility.config.UtilityFeatures;
import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.TextChannel;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Propagation;
@@ -29,7 +30,7 @@ import java.util.regex.Pattern;
@Component
@Slf4j
public class MessageEmbedListener extends ListenerAdapter {
public class MessageEmbedListener implements MessageReceivedListener {
@Autowired
private MessageCache messageCache;
@@ -56,10 +57,42 @@ public class MessageEmbedListener extends ListenerAdapter {
@Autowired
private TemplateService templateService;
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void createEmbedAndPostEmbed(@Nonnull Message postedMessage, CachedMessage message) {
MessageEmbeddedModel messageEmbeddedModel = buildTemplateParameter(postedMessage, message);
MessageToSend embed = templateService.renderEmbedTemplate(MESSAGE_EMBED_TEMPLATE, messageEmbeddedModel);
if(StringUtils.isBlank(embed.getMessage())) {
postedMessage.getChannel().sendMessage(embed.getEmbed()).queue();
} else {
postedMessage.getChannel().sendMessage(embed.getMessage()).embed(embed.getEmbed()).queue();
}
}
private MessageEmbeddedModel buildTemplateParameter(Message message, CachedMessage embeddedMessage) {
AChannel channel = channelManagementService.loadChannel(message.getChannel().getIdLong());
AServer server = serverManagementService.loadOrCreate(message.getGuild().getIdLong());
AUserInAServer user = userManagementService.loadUser(message.getMember());
Member author = bot.getMemberInServer(embeddedMessage.getServerId(), embeddedMessage.getAuthorId());
TextChannel sourceChannel = bot.getTextChannelFromServer(embeddedMessage.getServerId(), embeddedMessage.getChannelId()).get();
return MessageEmbeddedModel
.builder()
.channel(channel)
.server(server)
.member(message.getMember())
.aUserInAServer(user)
.author(author)
.sourceChannel(sourceChannel)
.embeddingUser(message.getMember())
.user(user.getUserReference())
.messageChannel(message.getChannel())
.guild(message.getGuild())
.embeddedMessage(embeddedMessage)
.build();
}
@Override
@Transactional
public void onGuildMessageReceived(@Nonnull GuildMessageReceivedEvent event) {
String messageRaw = event.getMessage().getContentRaw();
public void execute(Message message) {
String messageRaw = message.getContentRaw();
Matcher matcher = messageRegex.matcher(messageRaw);
boolean matched = false;
while(matcher.find()) {
@@ -68,52 +101,24 @@ public class MessageEmbedListener extends ListenerAdapter {
String channelId = matcher.group("channel");
String messageId = matcher.group("message");
String wholeLink = matcher.group("whole");
if(event.getMessage().getGuild().getId().equals(serverId)) {
if(message.getGuild().getId().equals(serverId)) {
Long serverIdLong = Long.parseLong(serverId);
Long channelIdLong = Long.parseLong(channelId);
Long messageIdLong = Long.parseLong(messageId);
messageRaw = messageRaw.replace(wholeLink, "");
messageCache.getMessageFromCache(serverIdLong, channelIdLong, messageIdLong).thenAccept(cachedMessage -> {
self.createEmbedAndPostEmbed(event, cachedMessage);
self.createEmbedAndPostEmbed(message, cachedMessage);
});
}
}
if(StringUtils.isBlank(messageRaw) && matched) {
event.getMessage().delete().queue();
message.delete().queue();
}
}
@NotNull
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void createEmbedAndPostEmbed(@Nonnull GuildMessageReceivedEvent event, CachedMessage message) {
MessageEmbeddedModel messageEmbeddedModel = buildTemplateParameter(event, message);
MessageToSend embed = templateService.renderEmbedTemplate(MESSAGE_EMBED_TEMPLATE, messageEmbeddedModel);
if(StringUtils.isBlank(embed.getMessage())) {
event.getChannel().sendMessage(embed.getEmbed()).queue();
} else {
event.getChannel().sendMessage(embed.getMessage()).embed(embed.getEmbed()).queue();
}
}
private MessageEmbeddedModel buildTemplateParameter(GuildMessageReceivedEvent event, CachedMessage embeddedMessage) {
AChannel channel = channelManagementService.loadChannel(event.getChannel().getIdLong());
AServer server = serverManagementService.loadOrCreate(event.getGuild().getIdLong());
AUserInAServer user = userManagementService.loadUser(event.getMember());
Member author = bot.getMemberInServer(embeddedMessage.getServerId(), embeddedMessage.getAuthorId());
return MessageEmbeddedModel
.builder()
.channel(channel)
.server(server)
.member(event.getMember())
.aUserInAServer(user)
.author(author)
.sourceChannel(event.getChannel())
.embeddingUser(event.getMember())
.user(user.getUserReference())
.textChannel(event.getChannel())
.guild(event.getGuild())
.embeddedMessage(embeddedMessage)
.build();
@Override
public String getFeature() {
return UtilityFeatures.LINK_EMBEDS;
}
}

View File

@@ -2,17 +2,18 @@ package dev.sheldan.abstracto.utility.listener;
import dev.sheldan.abstracto.core.listener.ReactedAddedListener;
import dev.sheldan.abstracto.core.listener.ReactedRemovedListener;
import dev.sheldan.abstracto.core.management.EmoteManagementService;
import dev.sheldan.abstracto.core.management.UserManagementService;
import dev.sheldan.abstracto.core.models.CachedMessage;
import dev.sheldan.abstracto.core.models.CachedReaction;
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.service.Bot;
import dev.sheldan.abstracto.core.management.ConfigManagementService;
import dev.sheldan.abstracto.core.service.MessageCache;
import dev.sheldan.abstracto.core.service.management.ConfigManagementService;
import dev.sheldan.abstracto.core.service.management.EmoteManagementService;
import dev.sheldan.abstracto.core.service.management.UserManagementService;
import dev.sheldan.abstracto.core.utils.EmoteUtils;
import dev.sheldan.abstracto.utility.config.UtilityFeatures;
import dev.sheldan.abstracto.utility.models.StarboardPost;
import dev.sheldan.abstracto.utility.service.StarboardService;
import dev.sheldan.abstracto.utility.service.management.StarboardPostManagementService;
@@ -69,7 +70,8 @@ public class StarboardListener implements ReactedAddedListener, ReactedRemovedLi
if(aEmote.isPresent()) {
AEmote emote = aEmote.get();
MessageReaction.ReactionEmote reactionEmote = addedReaction.getReactionEmote();
Optional<Emote> emoteInGuild = bot.getEmote(guildId, emote);
Optional<Emote> emoteInGuild = null;
emoteInGuild = bot.getEmote(guildId, emote);
if(EmoteUtils.isReactionEmoteAEmote(reactionEmote, emote, emoteInGuild.orElse(null))) {
Optional<CachedReaction> reactionOptional = EmoteUtils.getReactionFromMessageByEmote(message, emote);
updateStarboardPost(message, reactionOptional.orElse(null), userAdding, true);
@@ -99,10 +101,14 @@ public class StarboardListener implements ReactedAddedListener, ReactedRemovedLi
starboardService.createStarboardPost(message, userExceptAuthor, userReacting, author);
}
} else {
starboardPostOptional.ifPresent(this::completelyRemoveStarboardPost);
if(starboardPostOptional.isPresent()) {
this.completelyRemoveStarboardPost(starboardPostOptional.get());
}
}
} else {
starboardPostOptional.ifPresent(this::completelyRemoveStarboardPost);
if(starboardPostOptional.isPresent()) {
this.completelyRemoveStarboardPost(starboardPostOptional.get());
}
}
}
@@ -140,4 +146,9 @@ public class StarboardListener implements ReactedAddedListener, ReactedRemovedLi
private List<AUser> getUsersExcept(List<AUser> users, Long userId) {
return users.stream().filter(user -> !user.getId().equals(userId)).collect(Collectors.toList());
}
@Override
public String getFeature() {
return UtilityFeatures.STARBOARD;
}
}

View File

@@ -2,6 +2,7 @@ package dev.sheldan.abstracto.utility.listener;
import dev.sheldan.abstracto.core.listener.MessageDeletedListener;
import dev.sheldan.abstracto.core.models.CachedMessage;
import dev.sheldan.abstracto.utility.config.UtilityFeatures;
import dev.sheldan.abstracto.utility.models.StarboardPost;
import dev.sheldan.abstracto.utility.service.management.StarboardPostManagementService;
import org.springframework.beans.factory.annotation.Autowired;
@@ -22,4 +23,9 @@ public class StarboardPostDeletedListener implements MessageDeletedListener {
starboardPostManagementService.setStarboardPostIgnored(messageBefore.getMessageId(), true);
}
}
@Override
public String getFeature() {
return UtilityFeatures.STARBOARD;
}
}

View File

@@ -1,6 +1,6 @@
package dev.sheldan.abstracto.utility.repository.converter;
import dev.sheldan.abstracto.core.management.UserManagementService;
import dev.sheldan.abstracto.core.service.management.UserManagementService;
import dev.sheldan.abstracto.core.models.database.AUser;
import dev.sheldan.abstracto.core.service.Bot;
import dev.sheldan.abstracto.utility.models.template.starboard.StarStatsUser;

View File

@@ -1,6 +1,6 @@
package dev.sheldan.abstracto.utility.service;
import dev.sheldan.abstracto.core.management.ChannelManagementService;
import dev.sheldan.abstracto.core.service.management.ChannelManagementService;
import dev.sheldan.abstracto.core.models.AServerAChannelAUser;
import dev.sheldan.abstracto.core.models.database.AChannel;
import dev.sheldan.abstracto.core.models.database.AServer;
@@ -15,6 +15,7 @@ import dev.sheldan.abstracto.utility.models.template.ExecutedReminderModel;
import dev.sheldan.abstracto.utility.models.template.ReminderModel;
import dev.sheldan.abstracto.utility.service.management.ReminderManagementService;
import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.TextChannel;
import org.apache.commons.lang3.StringUtils;
@@ -70,9 +71,9 @@ public class RemindServiceBean implements ReminderService {
MessageToSend message = templateService.renderEmbedTemplate(REMINDER_EMBED_KEY, reminderModel);
String messageText = message.getMessage();
if(StringUtils.isBlank(messageText)) {
reminderModel.getTextChannel().sendMessage(message.getEmbed()).queue();
reminderModel.getMessageChannel().sendMessage(message.getEmbed()).queue();
} else {
reminderModel.getTextChannel().sendMessage(messageText).embed(message.getEmbed()).queue();
reminderModel.getMessageChannel().sendMessage(messageText).embed(message.getEmbed()).queue();
}
if(remindIn.getSeconds() < 60) {
@@ -93,6 +94,8 @@ public class RemindServiceBean implements ReminderService {
Reminder reminderToRemindFor = reminderManagementService.loadReminder(reminderId);
AServer server = reminderToRemindFor.getServer();
AChannel channel = reminderToRemindFor.getChannel();
Optional<Guild> guildToAnswerIn = bot.getGuildById(server.getId());
if(guildToAnswerIn.isPresent()) {
Optional<TextChannel> channelToAnswerIn = bot.getTextChannelFromServer(server.getId(), channel.getId());
// only send the message if the channel still exists, if not, only set the reminder to reminded.
if(channelToAnswerIn.isPresent()) {
@@ -106,7 +109,10 @@ public class RemindServiceBean implements ReminderService {
MessageToSend messageToSend = templateService.renderEmbedTemplate("remind_reminder", build);
channelToAnswerIn.get().sendMessage(messageToSend.getMessage()).embed(messageToSend.getEmbed()).queue();
} else {
log.warn("Channel {} in server {} to remind user did not exist anymore. Ignoring.", channel.getId(), server.getId());
log.warn("Channel {} in server {} to remind user did not exist anymore. Ignoring reminder {}", channel.getId(), server.getId(), reminderId);
}
} else {
log.warn("Guild {} to remind user in did not exist anymore. Ignoring reminder {}.", server.getId(), reminderId);
}
reminderManagementService.setReminded(reminderToRemindFor);
}

View File

@@ -1,8 +1,10 @@
package dev.sheldan.abstracto.utility.service;
import dev.sheldan.abstracto.core.management.EmoteManagementService;
import dev.sheldan.abstracto.core.management.PostTargetManagement;
import dev.sheldan.abstracto.core.management.UserManagementService;
import dev.sheldan.abstracto.core.exception.ChannelException;
import dev.sheldan.abstracto.core.exception.GuildException;
import dev.sheldan.abstracto.core.service.management.EmoteManagementService;
import dev.sheldan.abstracto.core.service.management.PostTargetManagement;
import dev.sheldan.abstracto.core.service.management.UserManagementService;
import dev.sheldan.abstracto.core.models.AServerChannelMessage;
import dev.sheldan.abstracto.core.models.CachedMessage;
import dev.sheldan.abstracto.core.models.database.*;
@@ -36,6 +38,8 @@ import java.util.stream.Collectors;
@Slf4j
public class StarboardServiceBean implements StarboardService {
public static final String STARBOARD_POSTTARGET = "starboard";
public static final String STARBOARD_POST_TEMPLATE = "starboard_post";
@Autowired
private Bot bot;
@@ -72,9 +76,9 @@ public class StarboardServiceBean implements StarboardService {
@Override
public void createStarboardPost(CachedMessage message, List<AUser> userExceptAuthor, AUserInAServer userReacting, AUserInAServer starredUser) {
StarboardPostModel starboardPostModel = buildStarboardPostModel(message, userExceptAuthor.size());
MessageToSend messageToSend = templateService.renderEmbedTemplate("starboard_post", starboardPostModel);
PostTarget starboard = postTargetManagement.getPostTarget("starboard", message.getServerId());
postTargetService.sendEmbedInPostTarget(messageToSend, "starboard", message.getServerId()).thenAccept(message1 -> {
MessageToSend messageToSend = templateService.renderEmbedTemplate(STARBOARD_POST_TEMPLATE, starboardPostModel);
PostTarget starboard = postTargetManagement.getPostTarget(STARBOARD_POSTTARGET, message.getServerId());
postTargetService.sendEmbedInPostTarget(messageToSend, STARBOARD_POSTTARGET, message.getServerId()).thenAccept(message1 -> {
AServerChannelMessage aServerChannelMessage = AServerChannelMessage
.builder()
.messageId(message1.getIdLong())

View File

@@ -1,6 +1,7 @@
package dev.sheldan.abstracto.utility.service;
import dev.sheldan.abstracto.core.management.EmoteManagementService;
import dev.sheldan.abstracto.core.service.EmoteService;
import dev.sheldan.abstracto.core.service.management.EmoteManagementService;
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
import dev.sheldan.abstracto.core.models.embed.MessageToSend;
import dev.sheldan.abstracto.core.service.Bot;
@@ -45,6 +46,9 @@ public class SuggestionServiceBean implements SuggestionService {
@Autowired
private EmoteManagementService emoteManagementService;
@Autowired
private EmoteService emoteService;
@Autowired
private MessageService messageService;
@@ -62,9 +66,9 @@ public class SuggestionServiceBean implements SuggestionService {
Guild guildById = instance.getGuildById(guildId);
if(guildById != null) {
postTargetService.sendEmbedInPostTarget(messageToSend, SUGGESTIONS_TARGET, guildId).thenAccept(message -> {
suggestionManagementService.setPostedMessage(suggestion, message);
messageService.addReactionToMessage(SUGGESTION_YES_EMOTE, guildId, message);
messageService.addReactionToMessage(SUGGESTION_NO_EMOTE, guildId, message);
suggestionManagementService.setPostedMessage(suggestion, message);
});
} else {
log.warn("Guild {} or member {} was not found when creating suggestion.", member.getGuild().getIdLong(), member.getIdLong());
@@ -122,4 +126,11 @@ public class SuggestionServiceBean implements SuggestionService {
suggestionManagementService.setSuggestionState(suggestion, SuggestionState.REJECTED);
updateSuggestion(text, log, suggestion);
}
@Override
public void validateSetup(Long serverId) {
emoteService.throwIfEmoteDoesNotExist(SUGGESTION_YES_EMOTE, serverId);
emoteService.throwIfEmoteDoesNotExist(SUGGESTION_NO_EMOTE, serverId);
postTargetService.throwIfPostTargetIsNotDefined(SUGGESTION_YES_EMOTE, serverId);
}
}

View File

@@ -1,8 +1,8 @@
package dev.sheldan.abstracto.utility.service.management;
import dev.sheldan.abstracto.core.management.ChannelManagementService;
import dev.sheldan.abstracto.core.management.ServerManagementService;
import dev.sheldan.abstracto.core.management.UserManagementService;
import dev.sheldan.abstracto.core.service.management.ChannelManagementService;
import dev.sheldan.abstracto.core.service.management.ServerManagementService;
import dev.sheldan.abstracto.core.service.management.UserManagementService;
import dev.sheldan.abstracto.core.models.database.AChannel;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.core.models.database.AUserInAServer;

View File

@@ -14,3 +14,9 @@ abstracto.scheduling.jobs.reminderJob.group=utility
abstracto.scheduling.jobs.reminderJob.clazz=dev.sheldan.abstracto.utility.jobs.ReminderJob
abstracto.scheduling.jobs.reminderJob.standAlone=false
abstracto.scheduling.jobs.reminderJob.active=true
abstracto.features.starboard=false
abstracto.features.reminder=false
abstracto.features.suggestion=false
abstracto.features.utility=false
abstracto.features.embeds=true

View File

@@ -7,4 +7,5 @@ public interface SuggestionService {
void createSuggestion(Member member, String text, SuggestionLog log);
void acceptSuggestion(Long suggestionId, String text, SuggestionLog log);
void rejectSuggestion(Long suggestionId, String text, SuggestionLog log);
void validateSetup(Long serverId);
}

View File

@@ -0,0 +1,19 @@
package dev.sheldan.abstracto.command;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.List;
@Component
public abstract class AbstractFeatureFlaggedCommand implements ConditionalCommand {
@Autowired
private FeatureEnabledCondition featureEnabledCondition;
@Override
public List<CommandCondition> getConditions() {
return Arrays.asList(featureEnabledCondition);
}
}

View File

@@ -2,10 +2,11 @@ package dev.sheldan.abstracto.command;
import dev.sheldan.abstracto.command.execution.CommandConfiguration;
import dev.sheldan.abstracto.command.execution.CommandContext;
import dev.sheldan.abstracto.command.execution.Result;
import dev.sheldan.abstracto.command.execution.CommandResult;
import dev.sheldan.abstracto.core.listener.FeatureAware;
public interface Command<T> {
public interface Command extends FeatureAware {
Result execute(CommandContext commandContext);
CommandResult execute(CommandContext commandContext);
CommandConfiguration getConfiguration();
}

View File

@@ -0,0 +1,7 @@
package dev.sheldan.abstracto.command;
import dev.sheldan.abstracto.command.execution.CommandContext;
public interface CommandCondition {
boolean shouldExecute(CommandContext commandContext, Command command);
}

View File

@@ -0,0 +1,7 @@
package dev.sheldan.abstracto.command;
import java.util.List;
public interface ConditionalCommand extends Command {
List<CommandCondition> getConditions();
}

View File

@@ -0,0 +1,22 @@
package dev.sheldan.abstracto.command;
import dev.sheldan.abstracto.command.execution.CommandContext;
import dev.sheldan.abstracto.core.service.management.FeatureFlagManagementService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class FeatureEnabledCondition implements CommandCondition {
@Autowired
private FeatureFlagManagementService featureFlagManagementService;
@Override
public boolean shouldExecute(CommandContext context, Command command) {
String featureName = command.getFeature();
if(featureName != null) {
return featureFlagManagementService.getFeatureFlagValue(featureName, context.getGuild().getIdLong());
}
return false;
}
}

View File

@@ -1,8 +1,8 @@
package dev.sheldan.abstracto.command;
import dev.sheldan.abstracto.command.execution.CommandContext;
import dev.sheldan.abstracto.command.execution.Result;
import dev.sheldan.abstracto.command.execution.CommandResult;
public interface PostCommandExecution {
void execute(CommandContext commandContext, Result result, Command command);
void execute(CommandContext commandContext, CommandResult commandResult, Command command);
}

View File

@@ -1,6 +1,6 @@
package dev.sheldan.abstracto.command;
public interface TemplatedException {
public interface Templatable {
String getTemplateName();
Object getTemplateModel();
}

View File

@@ -0,0 +1,25 @@
package dev.sheldan.abstracto.command.execution;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
@Getter @Setter @Builder
public class CommandResult {
private ResultState result;
private String message;
private Throwable throwable;
public static CommandResult fromSuccess() {
return CommandResult.builder().result(ResultState.SUCCESSFUL).build();
}
public static CommandResult fromError(String message){
return CommandResult.builder().result(ResultState.ERROR).message(message).build();
}
public static CommandResult fromError(String message, Throwable throwable) {
return CommandResult.builder().result(ResultState.ERROR).message(message).throwable(throwable).build();
}
}

View File

@@ -17,7 +17,7 @@ public class ContextConverter {
return builder
.member(commandContext.getAuthor())
.guild(commandContext.getGuild())
.textChannel(commandContext.getChannel())
.messageChannel(commandContext.getChannel())
.channel(commandContext.getUserInitiatedContext().getChannel())
.server(commandContext.getUserInitiatedContext().getServer())
.aUserInAServer(commandContext.getUserInitiatedContext().getAUserInAServer())

View File

@@ -1,25 +0,0 @@
package dev.sheldan.abstracto.command.execution;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
@Getter @Setter @Builder
public class Result {
private ResultState result;
private String message;
private Throwable throwable;
public static Result fromSuccess() {
return Result.builder().result(ResultState.SUCCESSFUL).build();
}
public static Result fromError(String message){
return Result.builder().result(ResultState.ERROR).message(message).build();
}
public static Result fromError(String message, Throwable throwable) {
return Result.builder().result(ResultState.ERROR).message(message).throwable(throwable).build();
}
}

View File

@@ -1,6 +0,0 @@
package dev.sheldan.abstracto.commands.management;
import dev.sheldan.abstracto.command.Command;
public abstract class AbstractCommand implements Command {
}

View File

@@ -6,8 +6,8 @@ import dev.sheldan.abstracto.command.execution.CommandConfiguration;
import dev.sheldan.abstracto.command.execution.Parameter;
import dev.sheldan.abstracto.command.meta.CommandRegistry;
import dev.sheldan.abstracto.command.meta.UnParsedCommandParameter;
import dev.sheldan.abstracto.commands.management.exception.CommandNotFoundException;
import dev.sheldan.abstracto.commands.management.exception.InsufficientParametersException;
import dev.sheldan.abstracto.commands.management.exception.CommandNotFound;
import dev.sheldan.abstracto.commands.management.exception.InsufficientParameters;
import net.dv8tion.jda.api.entities.Message;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@@ -35,7 +35,7 @@ public class CommandManager implements CommandRegistry {
boolean hasRemainderParameter = commandConfiguration.getParameters().stream().anyMatch(Parameter::isRemainder);
if(unParsedCommandParameter.getParameters().size() < commandConfiguration.getNecessaryParameterCount()) {
String nextParameterName = commandConfiguration.getParameters().get(commandConfiguration.getNecessaryParameterCount() - 1).getName();
throw new InsufficientParametersException("Insufficient parameters", o, nextParameterName);
throw new InsufficientParameters("Insufficient parameters", o, nextParameterName);
}
parameterFit = paramCountFits || hasRemainderParameter;
} else {
@@ -46,7 +46,7 @@ public class CommandManager implements CommandRegistry {
if(commandOptional.isPresent()){
return commandOptional.get();
}
throw new CommandNotFoundException("Command not found.");
throw new CommandNotFound("Command not found.");
}
public Command findCommand(String name) {
@@ -57,7 +57,7 @@ public class CommandManager implements CommandRegistry {
if(commandOptional.isPresent()){
return commandOptional.get();
}
throw new CommandNotFoundException("Command not found.");
throw new CommandNotFound("Command not found.");
}
@Override

View File

@@ -1,20 +1,24 @@
package dev.sheldan.abstracto.commands.management;
import dev.sheldan.abstracto.command.Command;
import dev.sheldan.abstracto.command.CommandCondition;
import dev.sheldan.abstracto.command.ConditionalCommand;
import dev.sheldan.abstracto.command.PostCommandExecution;
import dev.sheldan.abstracto.command.execution.*;
import dev.sheldan.abstracto.command.meta.UnParsedCommandParameter;
import dev.sheldan.abstracto.commands.management.exception.IncorrectParameterException;
import dev.sheldan.abstracto.commands.management.exception.ParameterTooLongException;
import dev.sheldan.abstracto.commands.management.exception.IncorrectParameter;
import dev.sheldan.abstracto.commands.management.exception.ParameterTooLong;
import dev.sheldan.abstracto.core.Constants;
import dev.sheldan.abstracto.core.management.ChannelManagementService;
import dev.sheldan.abstracto.core.management.ServerManagementService;
import dev.sheldan.abstracto.core.management.UserManagementService;
import dev.sheldan.abstracto.core.exception.*;
import dev.sheldan.abstracto.core.service.management.ChannelManagementService;
import dev.sheldan.abstracto.core.service.management.ServerManagementService;
import dev.sheldan.abstracto.core.service.management.UserManagementService;
import dev.sheldan.abstracto.core.models.database.AChannel;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.core.models.UserInitiatedServerContext;
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
import dev.sheldan.abstracto.core.utils.ParseUtils;
import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.entities.Emote;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.Message;
@@ -29,8 +33,10 @@ import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Nonnull;
import java.time.Duration;
import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
@Service
@Slf4j
public class CommandReceivedHandler extends ListenerAdapter {
@Autowired
@@ -74,18 +80,34 @@ public class CommandReceivedHandler extends ListenerAdapter {
foundCommand = commandManager.findCommandByParameters(commandName, unparsedParameter);
Parameters parsedParameters = getParsedParameters(unparsedParameter, foundCommand, event.getMessage());
CommandContext commandContext = commandContextBuilder.parameters(parsedParameters).build();
Result result = foundCommand.execute(commandContext);
if(foundCommand instanceof ConditionalCommand) {
ConditionalCommand castedCommand = (ConditionalCommand) foundCommand;
if (!shouldExecute(commandContext, foundCommand, castedCommand.getConditions())) {
throw new FeatureDisabledException(String.format("Feature `%s` has been disabled. Command is not usable", foundCommand.getFeature()));
}
}
CommandResult commandResult = foundCommand.execute(commandContext);
for (PostCommandExecution postCommandExecution : executions) {
postCommandExecution.execute(commandContext, result, foundCommand);
postCommandExecution.execute(commandContext, commandResult, foundCommand);
}
} catch (Exception e) {
Result result = Result.fromError(e.getMessage(), e);
CommandResult commandResult = CommandResult.fromError(e.getMessage(), e);
CommandContext commandContext = commandContextBuilder.build();
for (PostCommandExecution postCommandExecution : executions) {
postCommandExecution.execute(commandContext, result, foundCommand);
postCommandExecution.execute(commandContext, commandResult, foundCommand);
}
}
}
public boolean shouldExecute(CommandContext commandContext, Command command, List<CommandCondition> conditions) {
AtomicBoolean shouldExecute = new AtomicBoolean(true);
if(conditions != null) {
conditions.forEach(condition -> {
shouldExecute.set(shouldExecute.get() && condition.shouldExecute(commandContext, command));
});
}
return shouldExecute.get();
}
private UserInitiatedServerContext buildTemplateParameter(MessageReceivedEvent event) {
@@ -99,7 +121,7 @@ public class CommandReceivedHandler extends ListenerAdapter {
.member(event.getMember())
.aUserInAServer(user)
.user(user.getUserReference())
.textChannel(event.getTextChannel())
.messageChannel(event.getTextChannel())
.guild(event.getGuild())
.build();
}
@@ -122,7 +144,7 @@ public class CommandReceivedHandler extends ListenerAdapter {
}
String value = unParsedCommandParameter.getParameters().get(i);
if(param.getMaxLength() != null && (value.length() + Constants.PARAMETER_LIMIT) > param.getMaxLength()) {
throw new ParameterTooLongException("The passed parameter was too long.", command, param.getName(), value.length(), param.getMaxLength());
throw new ParameterTooLong("The passed parameter was too long.", command, param.getName(), value.length(), param.getMaxLength());
}
try {
if(param.getType().equals(Integer.class)){
@@ -143,18 +165,24 @@ public class CommandReceivedHandler extends ListenerAdapter {
} else {
parsedParameters.add(value);
}
} else if(param.getType().equals(Boolean.class)) {
parsedParameters.add(Boolean.valueOf(value));
} else if (param.getType().equals(Duration.class)) {
parsedParameters.add(ParseUtils.parseDuration(value));
} else {
if(!reminderActive) {
parsedParameters.add(value);
} else {
if(parsedParameters.size() == 0) {
parsedParameters.add(value);
} else {
int lastIndex = parsedParameters.size() - 1;
parsedParameters.set(lastIndex, parsedParameters.get(lastIndex) + " " + value);
}
}
}
} catch (NoSuchElementException e) {
throw new IncorrectParameterException("The passed parameters did not have the correct type.", command, param.getType(), param.getName());
throw new IncorrectParameter("The passed parameters did not have the correct type.", command, param.getType(), param.getName());
}
}

View File

@@ -1,10 +1,11 @@
package dev.sheldan.abstracto.commands.management.exception;
import dev.sheldan.abstracto.command.TemplatedException;
import dev.sheldan.abstracto.command.Templatable;
import dev.sheldan.abstracto.core.exception.AbstractoRunTimeException;
public class CommandNotFoundException extends RuntimeException implements TemplatedException {
public class CommandNotFound extends AbstractoRunTimeException implements Templatable {
public CommandNotFoundException(String s) {
public CommandNotFound(String s) {
super(s);
}

View File

@@ -1,17 +1,18 @@
package dev.sheldan.abstracto.commands.management.exception;
import dev.sheldan.abstracto.command.Command;
import dev.sheldan.abstracto.command.TemplatedException;
import dev.sheldan.abstracto.command.Templatable;
import dev.sheldan.abstracto.core.exception.AbstractoRunTimeException;
import java.util.HashMap;
public class IncorrectParameterException extends RuntimeException implements TemplatedException {
public class IncorrectParameter extends AbstractoRunTimeException implements Templatable {
private Command command;
private String parameterName;
private Class clazz;
public IncorrectParameterException(String s, Command command, Class expected, String parameterName) {
public IncorrectParameter(String s, Command command, Class expected, String parameterName) {
super(s);
this.command = command;
this.parameterName = parameterName;

View File

@@ -1,18 +1,19 @@
package dev.sheldan.abstracto.commands.management.exception;
import dev.sheldan.abstracto.command.TemplatedException;
import dev.sheldan.abstracto.command.Templatable;
import dev.sheldan.abstracto.command.Command;
import dev.sheldan.abstracto.core.exception.AbstractoRunTimeException;
import lombok.Getter;
import java.util.HashMap;
@Getter
public class InsufficientParametersException extends RuntimeException implements TemplatedException {
public class InsufficientParameters extends AbstractoRunTimeException implements Templatable {
private Command command;
private String parameterName;
public InsufficientParametersException(String s, Command command, String parameterName) {
public InsufficientParameters(String s, Command command, String parameterName) {
super(s);
this.command = command;
this.parameterName = parameterName;

View File

@@ -1,11 +1,12 @@
package dev.sheldan.abstracto.commands.management.exception;
import dev.sheldan.abstracto.command.Command;
import dev.sheldan.abstracto.command.TemplatedException;
import dev.sheldan.abstracto.command.Templatable;
import dev.sheldan.abstracto.core.exception.AbstractoRunTimeException;
import java.util.HashMap;
public class ParameterTooLongException extends RuntimeException implements TemplatedException {
public class ParameterTooLong extends AbstractoRunTimeException implements Templatable {
private Command command;
@@ -13,7 +14,7 @@ public class ParameterTooLongException extends RuntimeException implements Templ
private Integer actualLength;
private Integer maximumLength;
public ParameterTooLongException(String s, Command command, String parameterName, Integer actualLength, Integer maximumLength) {
public ParameterTooLong(String s, Command command, String parameterName, Integer actualLength, Integer maximumLength) {
super(s);
this.command = command;
this.parameterName = parameterName;

View File

@@ -2,9 +2,9 @@ package dev.sheldan.abstracto.commands.management.post;
import dev.sheldan.abstracto.command.Command;
import dev.sheldan.abstracto.command.PostCommandExecution;
import dev.sheldan.abstracto.command.TemplatedException;
import dev.sheldan.abstracto.command.Templatable;
import dev.sheldan.abstracto.command.execution.CommandContext;
import dev.sheldan.abstracto.command.execution.Result;
import dev.sheldan.abstracto.command.execution.CommandResult;
import dev.sheldan.abstracto.command.execution.ResultState;
import dev.sheldan.abstracto.templating.TemplateService;
import lombok.extern.slf4j.Slf4j;
@@ -19,16 +19,21 @@ public class ExceptionPostExecution implements PostCommandExecution {
private TemplateService templateService;
@Override
public void execute(CommandContext commandContext, Result result, Command command) {
if(result.getResult().equals(ResultState.ERROR)) {
if(result.getThrowable() != null) {
log.warn("Exception", result.getThrowable());
if(result.getThrowable() instanceof TemplatedException) {
TemplatedException exception = (TemplatedException) result.getThrowable();
public void execute(CommandContext commandContext, CommandResult commandResult, Command command) {
if(commandResult.getResult().equals(ResultState.ERROR)) {
Throwable throwable = commandResult.getThrowable();
if(throwable != null) {
if(throwable instanceof Templatable) {
Templatable exception = (Templatable) throwable;
String text = templateService.renderTemplate(exception.getTemplateName(), exception.getTemplateModel());
commandContext.getChannel().sendMessage(text).queue();
} else {
commandContext.getChannel().sendMessage(result.getThrowable().getClass().getSimpleName() + ": " + result.getMessage()).queue();
if(throwable.getCause() == null) {
commandContext.getChannel().sendMessage(throwable.getClass().getSimpleName() + ": " + commandResult.getMessage()).queue();
} else {
Throwable cause = throwable.getCause();
commandContext.getChannel().sendMessage(throwable.getClass().getSimpleName() + ": " + commandResult.getMessage() + ": " + cause.getClass().getSimpleName() + ":" + cause.getMessage()).queue();
}
}
}
}

View File

@@ -3,7 +3,7 @@ package dev.sheldan.abstracto.commands.management.post;
import dev.sheldan.abstracto.command.Command;
import dev.sheldan.abstracto.command.PostCommandExecution;
import dev.sheldan.abstracto.command.execution.CommandContext;
import dev.sheldan.abstracto.command.execution.Result;
import dev.sheldan.abstracto.command.execution.CommandResult;
import dev.sheldan.abstracto.command.execution.ResultState;
import dev.sheldan.abstracto.core.service.MessageService;
import org.springframework.beans.factory.annotation.Autowired;
@@ -18,11 +18,11 @@ public class ReactionPostExecution implements PostCommandExecution {
private MessageService messageService;
@Override
public void execute(CommandContext commandContext, Result result, Command command) {
if(result.getResult().equals(ResultState.ERROR)) {
public void execute(CommandContext commandContext, CommandResult commandResult, Command command) {
if(commandResult.getResult().equals(ResultState.ERROR)) {
messageService.addReactionToMessage(WARN_REACTION_EMOTE, commandContext.getGuild().getIdLong(), commandContext.getMessage());
if(result.getMessage() != null && result.getThrowable() == null){
commandContext.getChannel().sendMessage(result.getMessage()).queue();
if(commandResult.getMessage() != null && commandResult.getThrowable() == null){
commandContext.getChannel().sendMessage(commandResult.getMessage()).queue();
}
} else {
if(command.getConfiguration().isCausesReaction()){

View File

@@ -0,0 +1,5 @@
package dev.sheldan.abstracto.config;
public class AbstractoFeatures {
public static String CORE = "core";
}

View File

@@ -0,0 +1,16 @@
package dev.sheldan.abstracto.config;
import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import java.util.HashMap;
@Component
@Getter
@Setter
@ConfigurationProperties(prefix = "abstracto")
public class FeatureFlagConfig {
private HashMap<String, Boolean> features = new HashMap<>();
}

View File

@@ -0,0 +1,29 @@
package dev.sheldan.abstracto.config;
import dev.sheldan.abstracto.core.listener.ServerConfigListener;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.core.service.management.FeatureFlagManagementService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
@Slf4j
public class FeatureFlagListener implements ServerConfigListener {
@Autowired
private FeatureFlagConfig featureFlagConfig;
@Autowired
private FeatureFlagManagementService service;
@Override
public void updateServerConfig(AServer server) {
log.info("Setting up feature flags if necessary.");
featureFlagConfig.getFeatures().forEach((featureFlagKey, featureFlagValue) -> {
if(!service.getFeatureFlag(featureFlagKey, server.getId()).isPresent()) {
service.createFeatureFlag(featureFlagKey, server.getId(), featureFlagValue);
}
});
}
}

View File

@@ -0,0 +1,47 @@
package dev.sheldan.abstracto.core.commands;
import dev.sheldan.abstracto.command.Command;
import dev.sheldan.abstracto.command.execution.CommandConfiguration;
import dev.sheldan.abstracto.command.execution.CommandContext;
import dev.sheldan.abstracto.command.execution.CommandResult;
import dev.sheldan.abstracto.command.execution.Parameter;
import dev.sheldan.abstracto.config.AbstractoFeatures;
import dev.sheldan.abstracto.core.commands.utility.UtilityModule;
import dev.sheldan.abstracto.core.service.management.FeatureFlagManagementService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.List;
@Component
public class Disable implements Command {
@Autowired
private FeatureFlagManagementService featureFlagManagementService;
@Override
public CommandResult execute(CommandContext commandContext) {
String flagKey = (String) commandContext.getParameters().getParameters().get(0);
featureFlagManagementService.updateOrCreateFeatureFlag(flagKey, commandContext.getGuild().getIdLong(), false);
return CommandResult.fromSuccess();
}
@Override
public CommandConfiguration getConfiguration() {
Parameter featureName = Parameter.builder().name("featureName").type(String.class).description("The feature to disable.").build();
List<Parameter> parameters = Arrays.asList(featureName);
return CommandConfiguration.builder()
.name("disable")
.module(UtilityModule.UTILITY)
.parameters(parameters)
.description("Disables features for this server.")
.causesReaction(true)
.build();
}
@Override
public String getFeature() {
return AbstractoFeatures.CORE;
}
}

View File

@@ -0,0 +1,47 @@
package dev.sheldan.abstracto.core.commands;
import dev.sheldan.abstracto.command.Command;
import dev.sheldan.abstracto.command.execution.CommandConfiguration;
import dev.sheldan.abstracto.command.execution.CommandContext;
import dev.sheldan.abstracto.command.execution.CommandResult;
import dev.sheldan.abstracto.command.execution.Parameter;
import dev.sheldan.abstracto.config.AbstractoFeatures;
import dev.sheldan.abstracto.core.commands.utility.UtilityModule;
import dev.sheldan.abstracto.core.service.management.FeatureFlagManagementService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.List;
@Component
public class Enable implements Command {
@Autowired
private FeatureFlagManagementService featureFlagManagementService;
@Override
public CommandResult execute(CommandContext commandContext) {
String flagKey = (String) commandContext.getParameters().getParameters().get(0);
featureFlagManagementService.updateOrCreateFeatureFlag(flagKey, commandContext.getGuild().getIdLong(), true);
return CommandResult.fromSuccess();
}
@Override
public CommandConfiguration getConfiguration() {
Parameter featureName = Parameter.builder().name("featureName").type(String.class).description("The feature to enable.").build();
List<Parameter> parameters = Arrays.asList(featureName);
return CommandConfiguration.builder()
.name("enable")
.module(UtilityModule.UTILITY)
.parameters(parameters)
.description("Enables features for this server.")
.causesReaction(true)
.build();
}
@Override
public String getFeature() {
return AbstractoFeatures.CORE;
}
}

View File

@@ -2,10 +2,11 @@ package dev.sheldan.abstracto.core.commands.channels;
import dev.sheldan.abstracto.command.Command;
import dev.sheldan.abstracto.command.execution.*;
import dev.sheldan.abstracto.core.management.ChannelManagementService;
import dev.sheldan.abstracto.core.management.PostTargetManagement;
import dev.sheldan.abstracto.config.AbstractoFeatures;
import dev.sheldan.abstracto.core.models.command.PostTargetErrorModel;
import dev.sheldan.abstracto.core.service.PostTargetService;
import dev.sheldan.abstracto.core.service.management.ChannelManagementService;
import dev.sheldan.abstracto.core.service.management.PostTargetManagement;
import dev.sheldan.abstracto.templating.TemplateService;
import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.entities.Guild;
@@ -19,7 +20,7 @@ import java.util.List;
@Service
@Slf4j
public class PostTargetCommand implements Command {
public class PostTarget implements Command {
public static final String POST_TARGET_NO_TARGET_TEMPLATE = "posttarget_no_target";
public static final String POST_TARGET_INVALID_TARGET_TEMPLATE = "posttarget_invalid_target";
@@ -36,25 +37,25 @@ public class PostTargetCommand implements Command {
private TemplateService templateService;
@Override
public Result execute(CommandContext commandContext) {
public CommandResult execute(CommandContext commandContext) {
if(commandContext.getParameters().getParameters().isEmpty()) {
PostTargetErrorModel postTargetErrorModel = (PostTargetErrorModel) ContextConverter.fromCommandContext(commandContext, PostTargetErrorModel.class);
postTargetErrorModel.setValidPostTargets(postTargetService.getAvailablePostTargets());
String errorMessage = templateService.renderTemplate(POST_TARGET_NO_TARGET_TEMPLATE, postTargetErrorModel);
return Result.fromError(errorMessage);
return CommandResult.fromError(errorMessage);
}
String targetName = (String) commandContext.getParameters().getParameters().get(0);
if(!postTargetService.validPostTarget(targetName)) {
PostTargetErrorModel postTargetErrorModel = (PostTargetErrorModel) ContextConverter.fromCommandContext(commandContext, PostTargetErrorModel.class);
postTargetErrorModel.setValidPostTargets(postTargetService.getAvailablePostTargets());
String errorMessage = templateService.renderTemplate(POST_TARGET_INVALID_TARGET_TEMPLATE, postTargetErrorModel);
return Result.fromError(errorMessage);
return CommandResult.fromError(errorMessage);
}
GuildChannel channel = (GuildChannel) commandContext.getParameters().getParameters().get(1);
Guild guild = channel.getGuild();
postTargetManagement.createOrUpdate(targetName, guild.getIdLong(), channel.getIdLong());
log.info("Setting posttarget {} in {} to {}", targetName, guild.getIdLong(), channel.getId());
return Result.fromSuccess();
return CommandResult.fromSuccess();
}
@Override
@@ -70,4 +71,9 @@ public class PostTargetCommand implements Command {
.causesReaction(true)
.build();
}
@Override
public String getFeature() {
return AbstractoFeatures.CORE;
}
}

View File

@@ -3,12 +3,14 @@ package dev.sheldan.abstracto.core.commands.help;
import dev.sheldan.abstracto.command.*;
import dev.sheldan.abstracto.command.execution.*;
import dev.sheldan.abstracto.command.module.ModuleInfo;
import dev.sheldan.abstracto.config.AbstractoFeatures;
import dev.sheldan.abstracto.templating.TemplateService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Collections;
import java.util.List;
@Service
@@ -22,7 +24,7 @@ public class Help implements Command {
private TemplateService templateService;
@Override
public Result execute(CommandContext commandContext) {
public CommandResult execute(CommandContext commandContext) {
CommandHierarchy commandStructure = registry.getDetailedModules();
StringBuilder sb = new StringBuilder();
if(commandContext.getParameters().getParameters().isEmpty()){
@@ -53,7 +55,7 @@ public class Help implements Command {
}
commandContext.getChannel().sendMessage(sb.toString()).queue();
return Result.fromSuccess();
return CommandResult.fromSuccess();
}
private String getCommand(Command command){
@@ -132,4 +134,8 @@ public class Help implements Command {
.build();
}
@Override
public String getFeature() {
return AbstractoFeatures.CORE;
}
}

View File

@@ -1,17 +1,20 @@
package dev.sheldan.abstracto.core.commands.utility;
import dev.sheldan.abstracto.command.Command;
import dev.sheldan.abstracto.command.CommandCondition;
import dev.sheldan.abstracto.command.HelpInfo;
import dev.sheldan.abstracto.command.execution.CommandConfiguration;
import dev.sheldan.abstracto.command.execution.CommandContext;
import dev.sheldan.abstracto.command.execution.Parameter;
import dev.sheldan.abstracto.command.execution.Result;
import dev.sheldan.abstracto.command.execution.CommandResult;
import dev.sheldan.abstracto.config.AbstractoFeatures;
import dev.sheldan.abstracto.core.models.command.EchoModel;
import dev.sheldan.abstracto.templating.TemplateService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@Service
@@ -23,14 +26,14 @@ public class Echo implements Command {
private TemplateService templateService;
@Override
public Result execute(CommandContext commandContext) {
public CommandResult execute(CommandContext commandContext) {
StringBuilder sb = new StringBuilder();
commandContext.getParameters().getParameters().forEach(o -> {
sb.append(o.toString());
});
EchoModel model = EchoModel.builder().text(sb.toString()).build();
commandContext.getChannel().sendMessage(templateService.renderTemplate(TEMPLATE_NAME, model)).queue();
return Result.fromSuccess();
return CommandResult.fromSuccess();
}
@Override
@@ -47,4 +50,9 @@ public class Echo implements Command {
.help(helpInfo)
.build();
}
@Override
public String getFeature() {
return AbstractoFeatures.CORE;
}
}

View File

@@ -1,14 +1,19 @@
package dev.sheldan.abstracto.core.commands.utility;
import dev.sheldan.abstracto.command.Command;
import dev.sheldan.abstracto.command.CommandCondition;
import dev.sheldan.abstracto.command.execution.CommandConfiguration;
import dev.sheldan.abstracto.command.execution.CommandContext;
import dev.sheldan.abstracto.command.execution.Result;
import dev.sheldan.abstracto.command.execution.CommandResult;
import dev.sheldan.abstracto.config.AbstractoFeatures;
import dev.sheldan.abstracto.core.models.command.PingModel;
import dev.sheldan.abstracto.templating.TemplateService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Collections;
import java.util.List;
@Service
public class Ping implements Command {
@@ -18,12 +23,12 @@ public class Ping implements Command {
private TemplateService templateService;
@Override
public Result execute(CommandContext commandContext) {
public CommandResult execute(CommandContext commandContext) {
long ping = commandContext.getJda().getGatewayPing();
PingModel model = PingModel.builder().latency(ping).build();
String text = templateService.renderTemplate(PING_TEMPLATE, model);
commandContext.getChannel().sendMessage(text).queue();
return Result.fromSuccess();
return CommandResult.fromSuccess();
}
@Override
@@ -36,4 +41,9 @@ public class Ping implements Command {
.build();
}
@Override
public String getFeature() {
return AbstractoFeatures.CORE;
}
}

View File

@@ -3,11 +3,11 @@ package dev.sheldan.abstracto.core.commands.utility;
import dev.sheldan.abstracto.command.Command;
import dev.sheldan.abstracto.command.execution.CommandConfiguration;
import dev.sheldan.abstracto.command.execution.CommandContext;
import dev.sheldan.abstracto.command.execution.CommandResult;
import dev.sheldan.abstracto.command.execution.Parameter;
import dev.sheldan.abstracto.command.execution.Result;
import dev.sheldan.abstracto.core.exception.ConfigurationException;
import dev.sheldan.abstracto.core.management.EmoteManagementService;
import dev.sheldan.abstracto.config.AbstractoFeatures;
import dev.sheldan.abstracto.core.service.EmoteService;
import dev.sheldan.abstracto.core.service.management.EmoteManagementService;
import net.dv8tion.jda.api.entities.Emote;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@@ -25,7 +25,7 @@ public class SetEmote implements Command {
private EmoteService emoteService;
@Override
public Result execute(CommandContext commandContext) {
public CommandResult execute(CommandContext commandContext) {
String emoteKey = (String) commandContext.getParameters().getParameters().get(0);
Object o = commandContext.getParameters().getParameters().get(1);
if(o instanceof String) {
@@ -33,13 +33,10 @@ public class SetEmote implements Command {
emoteManagementService.setEmoteToDefaultEmote(emoteKey, emote, commandContext.getGuild().getIdLong());
} else {
Emote emote = (Emote) o;
if(emoteService.isEmoteUsableByBot(emote)) {
// todo check if usable
emoteManagementService.setEmoteToCustomEmote(emoteKey, emote, commandContext.getGuild().getIdLong());
} else {
throw new ConfigurationException("Emote is not usable by bot.");
}
}
return Result.fromSuccess();
return CommandResult.fromSuccess();
}
@Override
@@ -55,4 +52,9 @@ public class SetEmote implements Command {
.causesReaction(true)
.build();
}
@Override
public String getFeature() {
return AbstractoFeatures.CORE;
}
}

View File

@@ -1,6 +1,7 @@
package dev.sheldan.abstracto.core.service;
import dev.sheldan.abstracto.core.exception.NotFoundException;
import dev.sheldan.abstracto.core.exception.ChannelException;
import dev.sheldan.abstracto.core.exception.GuildException;
import dev.sheldan.abstracto.core.models.ServerChannelUser;
import dev.sheldan.abstracto.core.models.database.AEmote;
import lombok.extern.slf4j.Slf4j;
@@ -49,16 +50,14 @@ public class BotService implements Bot {
Member member = guild.getMemberById(userId);
return ServerChannelUser.builder().guild(guild).textChannel(textChannel).member(member).build();
} else {
throw new NotFoundException(String.format("Text channel %s not found in guild %s", channelId, serverId));
throw new ChannelException(String.format("Text channel %s not found in guild %s", channelId, serverId));
}
}
else {
throw new NotFoundException(String.format("Guild %s not found.", serverId));
throw new GuildException(String.format("Guild %s not found.", serverId));
}
}
@Override
public Member getMemberInServer(Long serverId, Long memberId) {
Guild guildById = instance.getGuildById(serverId);
@@ -90,9 +89,10 @@ public class BotService implements Bot {
Optional<Guild> guildById = getGuildById(serverId);
if(guildById.isPresent()) {
Guild guild = guildById.get();
return Optional.ofNullable(guild.getEmoteById(emote.getEmoteId()));
Emote emoteById = guild.getEmoteById(emote.getEmoteId());
return Optional.ofNullable(emoteById);
}
throw new NotFoundException(String.format("Not able to find emote %s in server %s", emote.getId(), serverId));
throw new GuildException(String.format("Not able to find server %s", serverId));
}
@Override
@@ -107,7 +107,7 @@ public class BotService implements Bot {
Guild guild = guildOptional.get();
return Optional.ofNullable(guild.getTextChannelById(textChannelId));
}
throw new NotFoundException(String.format("Not able to find guild %s", serverId));
throw new GuildException(String.format("Not able to find guild %s", serverId));
}
@Override

View File

@@ -1,5 +1,7 @@
package dev.sheldan.abstracto.core.service;
import dev.sheldan.abstracto.core.exception.ChannelException;
import dev.sheldan.abstracto.core.exception.GuildException;
import dev.sheldan.abstracto.core.models.database.AChannel;
import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.entities.Guild;
@@ -22,10 +24,12 @@ public class ChannelServiceBean implements ChannelService {
if(textChannel != null) {
textChannel.sendMessage(text).queue();
} else {
log.warn("Channel {} to post towards was not found in server {}", channel.getId(), channel.getServer().getId());
log.error("Channel {} to post towards was not found in server {}", channel.getId(), channel.getServer().getId());
throw new ChannelException(String.format("Channel %s to post to not found.", channel.getId()));
}
} else {
log.warn("Guild {} was not found when trying to post a message", channel.getServer().getId());
log.error("Guild {} was not found when trying to post a message", channel.getServer().getId());
throw new GuildException(String.format("Guild %s to post in channel %s was not found.", channel.getServer().getId(), channel.getId()));
}
}
}

View File

@@ -1,6 +1,6 @@
package dev.sheldan.abstracto.core.service;
import dev.sheldan.abstracto.core.management.ConfigManagementService;
import dev.sheldan.abstracto.core.service.management.ConfigManagementService;
import dev.sheldan.abstracto.core.models.database.AConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

View File

@@ -1,6 +1,8 @@
package dev.sheldan.abstracto.core.service;
import dev.sheldan.abstracto.core.exception.EmoteException;
import dev.sheldan.abstracto.core.models.database.AEmote;
import dev.sheldan.abstracto.core.service.management.EmoteManagementService;
import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.entities.Emote;
import net.dv8tion.jda.api.entities.Guild;
@@ -17,6 +19,9 @@ public class EmoteServiceBean implements EmoteService {
@Autowired
private Bot botService;
@Autowired
private EmoteManagementService emoteManagementService;
@Override
public boolean isEmoteUsableByBot(Emote emote) {
for (Guild guild : botService.getInstance().getGuilds()) {
@@ -59,4 +64,11 @@ public class EmoteServiceBean implements EmoteService {
public String getEmoteAsMention(AEmote emote, Long serverId) {
return this.getEmoteAsMention(emote, serverId, " ");
}
@Override
public void throwIfEmoteDoesNotExist(String emoteKey, Long serverId) {
if(!emoteManagementService.loadEmoteByName(emoteKey, serverId).isPresent()) {
throw new EmoteException(String.format("Emote %s not defined.", emoteKey));
}
}
}

View File

@@ -0,0 +1,17 @@
package dev.sheldan.abstracto.core.service;
import dev.sheldan.abstracto.core.service.management.FeatureFlagManagementService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class FeatureFlagServiceBean implements FeatureFlagService {
@Autowired
private FeatureFlagManagementService managementService;
@Override
public boolean isFeatureEnabled(String name, Long serverId) {
return managementService.getFeatureFlagValue(name, serverId);
}
}

View File

@@ -1,8 +1,9 @@
package dev.sheldan.abstracto.core.service;
import dev.sheldan.abstracto.core.exception.NotFoundException;
import dev.sheldan.abstracto.core.management.EmoteManagementService;
import dev.sheldan.abstracto.core.management.UserManagementService;
import dev.sheldan.abstracto.core.exception.ChannelException;
import dev.sheldan.abstracto.core.exception.GuildException;
import dev.sheldan.abstracto.core.service.management.EmoteManagementService;
import dev.sheldan.abstracto.core.service.management.UserManagementService;
import dev.sheldan.abstracto.core.models.CachedMessage;
import dev.sheldan.abstracto.core.models.CachedReaction;
import dev.sheldan.abstracto.core.models.database.AUser;
@@ -89,12 +90,12 @@ public class MessageCacheBean implements MessageCache {
buildCachedMessageFromMessage(future, message);
});
} else {
log.warn("Not able to load message {} in channel {} in guild {}. Text channel not found.", messageId, textChannelId, guildId);
future.completeExceptionally(new NotFoundException(String.format("Not able to load message %s. Text channel %s not found in guild %s", messageId, textChannelId, guildId)));
log.error("Not able to load message {} in channel {} in guild {}. Text channel not found.", messageId, textChannelId, guildId);
future.completeExceptionally(new ChannelException(String.format("Not able to load message %s. Text channel %s not found in guild %s", messageId, textChannelId, guildId)));
}
} else {
log.warn("Not able to load message {} in channel {} in guild {}. Guild not found.", messageId, textChannelId, guildId);
future.completeExceptionally(new NotFoundException(String.format("Not able to load message %s. Guild %s not found.", messageId, guildId)));
log.error("Not able to load message {} in channel {} in guild {}. Guild not found.", messageId, textChannelId, guildId);
future.completeExceptionally(new GuildException(String.format("Not able to load message %s. Guild %s not found.", messageId, guildId)));
}
}

View File

@@ -1,7 +1,8 @@
package dev.sheldan.abstracto.core.service;
import dev.sheldan.abstracto.core.exception.NotFoundException;
import dev.sheldan.abstracto.core.management.EmoteManagementService;
import dev.sheldan.abstracto.core.exception.EmoteException;
import dev.sheldan.abstracto.core.exception.GuildException;
import dev.sheldan.abstracto.core.service.management.EmoteManagementService;
import dev.sheldan.abstracto.core.models.database.AEmote;
import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.entities.Emote;
@@ -31,23 +32,23 @@ public class MessageServiceBean implements MessageService {
if(aEmote.isPresent()) {
AEmote emote = aEmote.get();
if(emote.getCustom()) {
Emote emoteById = guild.getEmoteById(emote.getEmoteId());
Emote emoteById = bot.getInstance().getEmoteById(emote.getEmoteId());
if(emoteById != null) {
message.addReaction(emoteById).queue();
} else {
log.warn("Emote with key {} and id {} for guild {} was not found.", emoteKey, emote.getEmoteId(), guild.getId());
throw new NotFoundException(String.format("Emote with key `%s` and id %s in guild %s was not found. Check whether or not the configured emote is available.", emoteKey, emote.getEmoteId(), guild.getIdLong()));
log.error("Emote with key {} and id {} for guild {} was not found.", emoteKey, emote.getEmoteId(), guild.getId());
throw new EmoteException(String.format("Emote with key `%s` and id %s in guild %s was not found. Check whether or not the configured emote is available.", emoteKey, emote.getEmoteId(), guild.getIdLong()));
}
} else {
message.addReaction(emote.getEmoteKey()).queue();
}
} else {
log.warn("Cannot add reaction, emote {} not defined for server {}.", emoteKey, serverId);
throw new NotFoundException(String.format("Cannot add reaction. Emote `%s` not defined in server %s. Define the emote via the setEmote command.", emoteKey, serverId));
log.error("Cannot add reaction, emote {} not defined for server {}.", emoteKey, serverId);
throw new EmoteException(String.format("Cannot add reaction. Emote `%s` not defined in server %s. Define the emote via the setEmote command.", emoteKey, serverId));
}
} else {
log.warn("Cannot add reaction, guild not found {}", serverId);
throw new NotFoundException(String.format("Cannot add reaction, guild %s not found.", serverId));
log.error("Cannot add reaction, guild not found {}", serverId);
throw new GuildException(String.format("Cannot add reaction, guild %s not found.", serverId));
}
}
}

View File

@@ -1,9 +1,10 @@
package dev.sheldan.abstracto.core.service;
import dev.sheldan.abstracto.core.DynamicKeyLoader;
import dev.sheldan.abstracto.core.exception.ConfigurationException;
import dev.sheldan.abstracto.core.management.PostTargetManagement;
import dev.sheldan.abstracto.core.management.ServerManagementService;
import dev.sheldan.abstracto.core.exception.ChannelException;
import dev.sheldan.abstracto.core.exception.GuildException;
import dev.sheldan.abstracto.core.service.management.PostTargetManagement;
import dev.sheldan.abstracto.core.service.management.ServerManagementService;
import dev.sheldan.abstracto.core.models.database.PostTarget;
import dev.sheldan.abstracto.core.models.embed.MessageToSend;
import lombok.extern.slf4j.Slf4j;
@@ -54,13 +55,14 @@ public class PostTargetServiceBean implements PostTargetService {
if(textChannelById != null) {
return textChannelById;
} else {
log.warn("Incorrect post target configuration: {} points to {} on server {}", target.getName(),
log.error("Incorrect post target configuration: {} points to {} on server {}", target.getName(),
target.getChannelReference().getId(), target.getServerReference().getId());
throw new ChannelException(String.format("Incorrect post target configuration. The channel %s of target %s cannot be found",
target.getChannelReference().getId(), target.getChannelReference().getId()));
}
} else {
log.warn("Incorrect post target configuration: Guild id {} was not found.", target.getServerReference().getId());
throw new GuildException(String.format("Incorrect post target configuration. Guild %s cannot be found.", target.getServerReference().getId()));
}
throw new ConfigurationException("Incorrect post target configuration.");
}
private PostTarget getPostTarget(String postTargetName, Long serverId) {
@@ -68,8 +70,8 @@ public class PostTargetServiceBean implements PostTargetService {
if(postTarget != null) {
return postTarget;
} else {
log.warn("PostTarget {} in server {} was not found!", postTargetName, serverId);
throw new ConfigurationException(String.format("Incorrect post target configuration: Post target %s was not found.", postTargetName));
log.error("PostTarget {} in server {} was not found!", postTargetName, serverId);
throw new ChannelException(String.format("Incorrect post target configuration: Post target %s was not found.", postTargetName));
}
}
@@ -123,8 +125,10 @@ public class PostTargetServiceBean implements PostTargetService {
existingMessage -> existingMessage
.editMessage(messageToSend.getEmbed())
.submit().thenAccept(future::complete),
throwable -> sendEmbedInPostTarget(messageToSend, target)
.thenAccept(future::complete));
throwable -> {
sendEmbedInPostTarget(messageToSend, target)
.thenAccept(future::complete);
});
} else {
textChannelForPostTarget
.retrieveMessageById(messageId)
@@ -133,8 +137,10 @@ public class PostTargetServiceBean implements PostTargetService {
.editMessage(messageToSend.getMessage())
.embed(messageToSend.getEmbed())
.submit().thenAccept(future::complete),
throwable -> sendEmbedInPostTarget(messageToSend, target)
.thenAccept(future::complete));
throwable -> {
sendEmbedInPostTarget(messageToSend, target)
.thenAccept(future::complete);
});
}
}
@@ -144,6 +150,14 @@ public class PostTargetServiceBean implements PostTargetService {
this.editOrCreatedInPostTarget(messageId, messageToSend, postTarget, future);
}
@Override
public void throwIfPostTargetIsNotDefined(String name, Long serverId) throws ChannelException {
PostTarget postTarget = postTargetManagement.getPostTarget(name, serverId);
if(postTarget == null) {
throw new ChannelException(String.format("Post target %s is not defined.", name));
}
}
@Override
public CompletableFuture<Message> editEmbedInPostTarget(Long messageId, MessageToSend message, String postTargetName, Long serverId) {
PostTarget postTarget = this.getPostTarget(postTargetName, serverId);

View File

@@ -2,9 +2,9 @@ package dev.sheldan.abstracto.core.service;
import dev.sheldan.abstracto.core.listener.ServerConfigListener;
import dev.sheldan.abstracto.core.utils.SnowflakeUtils;
import dev.sheldan.abstracto.core.management.ChannelManagementService;
import dev.sheldan.abstracto.core.management.RoleManagementService;
import dev.sheldan.abstracto.core.management.ServerManagementService;
import dev.sheldan.abstracto.core.service.management.ChannelManagementService;
import dev.sheldan.abstracto.core.service.management.RoleManagementService;
import dev.sheldan.abstracto.core.service.management.ServerManagementService;
import dev.sheldan.abstracto.core.models.database.AChannel;
import dev.sheldan.abstracto.core.models.AChannelType;
import dev.sheldan.abstracto.core.models.database.ARole;

View File

@@ -2,7 +2,6 @@ package dev.sheldan.abstracto.core.service.management;
import dev.sheldan.abstracto.core.models.database.AChannel;
import dev.sheldan.abstracto.core.models.AChannelType;
import dev.sheldan.abstracto.core.management.ChannelManagementService;
import dev.sheldan.abstracto.repository.ChannelRepository;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;

View File

@@ -1,9 +1,7 @@
package dev.sheldan.abstracto.core.service.management;
import dev.sheldan.abstracto.core.management.ServerManagementService;
import dev.sheldan.abstracto.core.models.database.AConfig;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.core.management.ConfigManagementService;
import dev.sheldan.abstracto.repository.ConfigRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

View File

@@ -1,11 +1,10 @@
package dev.sheldan.abstracto.core.service.management;
import dev.sheldan.abstracto.core.DynamicKeyLoader;
import dev.sheldan.abstracto.core.exception.ConfigurationException;
import dev.sheldan.abstracto.core.management.EmoteManagementService;
import dev.sheldan.abstracto.core.management.ServerManagementService;
import dev.sheldan.abstracto.core.exception.EmoteException;
import dev.sheldan.abstracto.core.models.database.AEmote;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.core.service.Bot;
import dev.sheldan.abstracto.repository.EmoteRepository;
import net.dv8tion.jda.api.entities.Emote;
import org.springframework.beans.factory.annotation.Autowired;
@@ -26,6 +25,9 @@ public class EmoteManagementServiceBean implements EmoteManagementService {
@Autowired
private DynamicKeyLoader dynamicKeyLoader;
@Autowired
private Bot botService;
@Override
public AEmote loadEmote(Long id) {
return repository.getOne(id);
@@ -174,7 +176,7 @@ public class EmoteManagementServiceBean implements EmoteManagementService {
private void validateEmoteName(String name) {
List<String> possibleEmotes = dynamicKeyLoader.getEmoteNamesAsList();
if(!possibleEmotes.contains(name)) {
throw new ConfigurationException("Emote `" + name + "` is not defined. Possible values are: " + String.join(", ", possibleEmotes));
throw new EmoteException("Emote `" + name + "` is not defined. Possible values are: " + String.join(", ", possibleEmotes));
}
}
}

View File

@@ -0,0 +1,60 @@
package dev.sheldan.abstracto.core.service.management;
import dev.sheldan.abstracto.core.models.database.AFeatureFlag;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.repository.FeatureFlagRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Optional;
@Component
public class FeatureFlagManagementServiceBean implements FeatureFlagManagementService {
@Autowired
private FeatureFlagRepository repository;
@Autowired
private ServerManagementService serverManagementService;
@Override
public void createFeatureFlag(String key, Long serverId, Boolean newValue) {
AServer server = serverManagementService.loadOrCreate(serverId);
createFeatureFlag(key, server, newValue);
}
@Override
public void createFeatureFlag(String key, AServer server, Boolean newValue) {
AFeatureFlag featureFlag = AFeatureFlag
.builder()
.enabled(newValue)
.key(key)
.server(server)
.build();
repository.save(featureFlag);
}
@Override
public boolean getFeatureFlagValue(String key, Long serverId) {
Optional<AFeatureFlag> featureFlag = getFeatureFlag(key, serverId);
return featureFlag.isPresent() && featureFlag.get().isEnabled();
}
@Override
public void updateOrCreateFeatureFlag(String key, Long serverId, Boolean newValue) {
Optional<AFeatureFlag> existing = getFeatureFlag(key, serverId);
if(existing.isPresent()) {
AFeatureFlag flag = existing.get();
flag.setEnabled(newValue);
repository.save(flag);
} else {
createFeatureFlag(key, serverId, newValue);
}
}
@Override
public Optional<AFeatureFlag> getFeatureFlag(String key, Long serverId) {
AServer server = serverManagementService.loadOrCreate(serverId);
return Optional.ofNullable(repository.findByServerAndKey(server, key));
}
}

View File

@@ -2,12 +2,10 @@ package dev.sheldan.abstracto.core.service.management;
import dev.sheldan.abstracto.core.DynamicKeyLoader;
import dev.sheldan.abstracto.core.exception.ConfigurationException;
import dev.sheldan.abstracto.core.exception.PostTargetException;
import dev.sheldan.abstracto.core.models.database.AChannel;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.core.models.database.PostTarget;
import dev.sheldan.abstracto.core.management.ChannelManagementService;
import dev.sheldan.abstracto.core.management.PostTargetManagement;
import dev.sheldan.abstracto.core.management.ServerManagementService;
import dev.sheldan.abstracto.core.service.PostTargetService;
import dev.sheldan.abstracto.repository.PostTargetRepository;
import lombok.extern.slf4j.Slf4j;
@@ -36,7 +34,7 @@ public class PostTargetManagementBean implements PostTargetManagement {
@Override
public void createPostTarget(String name, AServer server, AChannel targetChannel) {
if(!postTargetService.validPostTarget(name)) {
throw new ConfigurationException("PostTarget not found. Possible values are: " + String.join(", ", dynamicKeyLoader.getPostTargetsAsList()));
throw new PostTargetException("PostTarget not found. Possible values are: " + String.join(", ", dynamicKeyLoader.getPostTargetsAsList()));
}
log.info("Creating post target {} pointing towards {}", name, targetChannel);
postTargetRepository.save(PostTarget.builder().name(name).channelReference(targetChannel).serverReference(server).build());
@@ -44,7 +42,7 @@ public class PostTargetManagementBean implements PostTargetManagement {
@Override
public void createOrUpdate(String name, AServer server, AChannel targetChannel) {
PostTarget existing = postTargetRepository.findPostTargetByName(name);
PostTarget existing = postTargetRepository.findPostTargetByNameAndServerReference(name, server);
if(existing == null){
this.createPostTarget(name, server, targetChannel);
} else {
@@ -68,7 +66,7 @@ public class PostTargetManagementBean implements PostTargetManagement {
@Override
@Cacheable("posttargets")
public PostTarget getPostTarget(String name, AServer server) {
return postTargetRepository.findPostTargetByName(name);
return postTargetRepository.findPostTargetByNameAndServerReference(name, server);
}
@Override

View File

@@ -1,7 +1,6 @@
package dev.sheldan.abstracto.core.service.management;
import dev.sheldan.abstracto.core.models.database.ARole;
import dev.sheldan.abstracto.core.management.RoleManagementService;
import dev.sheldan.abstracto.repository.RoleRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

View File

@@ -1,9 +1,5 @@
package dev.sheldan.abstracto.core.service.management;
import dev.sheldan.abstracto.core.management.ChannelManagementService;
import dev.sheldan.abstracto.core.management.PostTargetManagement;
import dev.sheldan.abstracto.core.management.ServerManagementService;
import dev.sheldan.abstracto.core.management.UserManagementService;
import dev.sheldan.abstracto.core.models.database.*;
import dev.sheldan.abstracto.repository.ServerRepository;
import lombok.extern.slf4j.Slf4j;

View File

@@ -1,7 +1,5 @@
package dev.sheldan.abstracto.core.service.management;
import dev.sheldan.abstracto.core.management.ServerManagementService;
import dev.sheldan.abstracto.core.management.UserManagementService;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.core.models.database.AUser;
import dev.sheldan.abstracto.core.models.database.AUserInAServer;

View File

@@ -1,7 +1,7 @@
package dev.sheldan.abstracto.listener;
import dev.sheldan.abstracto.core.management.ChannelManagementService;
import dev.sheldan.abstracto.core.management.ServerManagementService;
import dev.sheldan.abstracto.core.service.management.ChannelManagementService;
import dev.sheldan.abstracto.core.service.management.ServerManagementService;
import dev.sheldan.abstracto.core.models.AChannelType;
import dev.sheldan.abstracto.core.models.database.AChannel;
import dev.sheldan.abstracto.core.models.database.AServer;

View File

@@ -1,63 +0,0 @@
package dev.sheldan.abstracto.listener;
import dev.sheldan.abstracto.core.service.PostTargetService;
import dev.sheldan.abstracto.core.management.ServerManagementService;
import dev.sheldan.abstracto.templating.TemplateService;
import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.entities.User;
import net.dv8tion.jda.api.events.guild.member.GuildMemberJoinEvent;
import net.dv8tion.jda.api.events.guild.member.GuildMemberLeaveEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
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;
@Service
@Slf4j
public class JoinLeaveListener extends ListenerAdapter {
private static final String USER_JOIN_TEMPLATE = "user_join";
private static final String USER_LEAVE_TEMPLATE = "user_leave";
private static final String JOIN_LOG_TARGET = "joinLog";
private static final String LEAVE_LOG_TARGET = "leaveLog";
@Autowired
private ServerManagementService serverManagementService;
@Autowired
private TemplateService templateService;
@Autowired
private PostTargetService postTargetService;
@Override
@Transactional
public void onGuildMemberJoin(@Nonnull GuildMemberJoinEvent event) {
String text = getRenderedEvent(event.getUser(), USER_JOIN_TEMPLATE);
postTargetService.sendTextInPostTarget(text, JOIN_LOG_TARGET, event.getGuild().getIdLong());
}
@Override
@Transactional
public void onGuildMemberLeave(@Nonnull GuildMemberLeaveEvent event) {
String text = getRenderedEvent(event.getUser(), USER_LEAVE_TEMPLATE);
postTargetService.sendTextInPostTarget(text, LEAVE_LOG_TARGET, event.getGuild().getIdLong());
}
@NotNull
private HashMap<String, Object> getUserParameter(@Nonnull User user) {
HashMap<String, Object> parameters = new HashMap<>();
parameters.put("user", user);
parameters.put("userMention", user.getAsMention());
return parameters;
}
private String getRenderedEvent(User user, String templateName) {
HashMap<String, Object> parameters = getUserParameter(user);
return templateService.renderTemplate(templateName, parameters);
}
}

View File

@@ -0,0 +1,40 @@
package dev.sheldan.abstracto.listener;
import dev.sheldan.abstracto.core.exception.AbstractoRunTimeException;
import dev.sheldan.abstracto.core.listener.JoinListener;
import dev.sheldan.abstracto.core.service.FeatureFlagService;
import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.events.guild.member.GuildMemberJoinEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
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.List;
@Service
@Slf4j
public class JoinListenerBean extends ListenerAdapter {
@Autowired
private List<JoinListener> listenerList;
@Autowired
private FeatureFlagService featureFlagService;
@Override
@Transactional
public void onGuildMemberJoin(@Nonnull GuildMemberJoinEvent event) {
listenerList.forEach(joinListener -> {
if (!featureFlagService.isFeatureEnabled(joinListener.getFeature(), event.getGuild().getIdLong())) {
return;
}
try {
joinListener.execute(event.getMember(), event.getGuild());
} catch (AbstractoRunTimeException e) {
log.error("Listener {} failed with exception:", joinListener.getClass().getName(), e);
}
});
}
}

View File

@@ -0,0 +1,40 @@
package dev.sheldan.abstracto.listener;
import dev.sheldan.abstracto.core.exception.AbstractoRunTimeException;
import dev.sheldan.abstracto.core.listener.LeaveListener;
import dev.sheldan.abstracto.core.service.FeatureFlagService;
import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.events.guild.member.GuildMemberLeaveEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
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.List;
@Service
@Slf4j
public class LeaveListenerBean extends ListenerAdapter {
@Autowired
private List<LeaveListener> listenerList;
@Autowired
private FeatureFlagService featureFlagService;
@Override
@Transactional
public void onGuildMemberLeave(@Nonnull GuildMemberLeaveEvent event) {
listenerList.forEach(leaveListener -> {
if(!featureFlagService.isFeatureEnabled(leaveListener.getFeature(), event.getGuild().getIdLong())) {
return;
}
try {
leaveListener.execute(event.getMember(), event.getGuild());
} catch (AbstractoRunTimeException e) {
log.error("Listener {} failed with exception:", leaveListener.getClass().getName(), e);
}
});
}
}

View File

@@ -1,21 +0,0 @@
package dev.sheldan.abstracto.listener;
import dev.sheldan.abstracto.core.service.MessageCache;
import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.Nonnull;
@Component
public class MessageCacheListener extends ListenerAdapter {
@Autowired
private MessageCache messageCache;
@Override
public void onGuildMessageReceived(@Nonnull GuildMessageReceivedEvent event) {
messageCache.putMessageInCache(event.getMessage());
}
}

View File

@@ -1,7 +1,9 @@
package dev.sheldan.abstracto.listener;
import dev.sheldan.abstracto.core.exception.AbstractoRunTimeException;
import dev.sheldan.abstracto.core.listener.MessageDeletedListener;
import dev.sheldan.abstracto.core.models.CachedMessage;
import dev.sheldan.abstracto.core.service.FeatureFlagService;
import dev.sheldan.abstracto.core.service.MessageCache;
import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.events.message.guild.GuildMessageDeleteEvent;
@@ -25,6 +27,9 @@ public class MessageDeletedListenerBean extends ListenerAdapter {
@Autowired
private MessageDeletedListenerBean self;
@Autowired
private FeatureFlagService featureFlagService;
@Override
@Transactional
public void onGuildMessageDelete(@Nonnull GuildMessageDeleteEvent event) {
@@ -36,10 +41,13 @@ public class MessageDeletedListenerBean extends ListenerAdapter {
@Transactional
public void executeListener(CachedMessage cachedMessage) {
listener.forEach(messageDeletedListener -> {
if(!featureFlagService.isFeatureEnabled(messageDeletedListener.getFeature(), cachedMessage.getServerId())) {
return;
}
try {
messageDeletedListener.execute(cachedMessage);
} catch (Exception e) {
log.warn("Listener {} failed with exception:", messageDeletedListener.getClass().getName(), e);
} catch (AbstractoRunTimeException e) {
log.error("Listener {} failed with exception:", messageDeletedListener.getClass().getName(), e);
}
});
}

View File

@@ -0,0 +1,41 @@
package dev.sheldan.abstracto.listener;
import dev.sheldan.abstracto.core.listener.MessageReceivedListener;
import dev.sheldan.abstracto.core.service.FeatureFlagService;
import dev.sheldan.abstracto.core.service.MessageCache;
import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Nonnull;
import java.util.List;
@Component
@Slf4j
public class MessageReceivedListenerBean extends ListenerAdapter {
@Autowired
private MessageCache messageCache;
@Autowired
private List<MessageReceivedListener> listenerList;
@Autowired
private FeatureFlagService featureFlagService;
@Override
@Transactional
public void onGuildMessageReceived(@Nonnull GuildMessageReceivedEvent event) {
messageCache.putMessageInCache(event.getMessage());
listenerList.forEach(messageReceivedListener -> {
if(!featureFlagService.isFeatureEnabled(messageReceivedListener.getFeature(), event.getGuild().getIdLong())) {
return;
}
messageReceivedListener.execute(event.getMessage());
});
}
}

View File

@@ -1,7 +1,9 @@
package dev.sheldan.abstracto.listener;
import dev.sheldan.abstracto.core.exception.AbstractoRunTimeException;
import dev.sheldan.abstracto.core.listener.MessageTextUpdatedListener;
import dev.sheldan.abstracto.core.models.CachedMessage;
import dev.sheldan.abstracto.core.service.FeatureFlagService;
import dev.sheldan.abstracto.core.service.MessageCache;
import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.entities.Message;
@@ -27,6 +29,9 @@ public class MessageUpdatedListener extends ListenerAdapter {
@Autowired
private MessageUpdatedListener self;
@Autowired
private FeatureFlagService featureFlagService;
@Override
public void onGuildMessageUpdate(@Nonnull GuildMessageUpdateEvent event) {
Message message = event.getMessage();
@@ -40,7 +45,14 @@ public class MessageUpdatedListener extends ListenerAdapter {
@Transactional
public void executeListener(Message message, CachedMessage cachedMessage) {
listener.forEach(messageTextUpdatedListener -> {
if(!featureFlagService.isFeatureEnabled(messageTextUpdatedListener.getFeature(), message.getGuild().getIdLong())) {
return;
}
try {
messageTextUpdatedListener.execute(cachedMessage, message);
} catch (AbstractoRunTimeException e) {
log.error(String.format("Failed to execute listener. %s", messageTextUpdatedListener.getClass().getName()), e);
}
});
}
}

View File

@@ -1,8 +1,10 @@
package dev.sheldan.abstracto.listener;
import dev.sheldan.abstracto.core.exception.AbstractoRunTimeException;
import dev.sheldan.abstracto.core.listener.ReactedAddedListener;
import dev.sheldan.abstracto.core.listener.ReactedRemovedListener;
import dev.sheldan.abstracto.core.management.UserManagementService;
import dev.sheldan.abstracto.core.service.FeatureFlagService;
import dev.sheldan.abstracto.core.service.management.UserManagementService;
import dev.sheldan.abstracto.core.models.CachedMessage;
import dev.sheldan.abstracto.core.models.CachedReaction;
import dev.sheldan.abstracto.core.models.database.AUser;
@@ -46,6 +48,8 @@ public class ReactionUpdatedListener extends ListenerAdapter {
@Autowired
private ReactionUpdatedListener self;
@Autowired
private FeatureFlagService featureFlagService;
@Override
@Transactional
@@ -91,13 +95,16 @@ public class ReactionUpdatedListener extends ListenerAdapter {
public void callAddedListeners(@Nonnull GuildMessageReactionAddEvent event, CachedMessage cachedMessage, CachedReaction reaction) {
AUserInAServer userInAServer = userManagementService.loadUser(event.getGuild().getIdLong(), event.getUserIdLong());
addReactionIfNotThere(cachedMessage, reaction, userInAServer.getUserReference());
try {
addedListenerList.forEach(reactedAddedListener -> {
reactedAddedListener.executeReactionAdded(cachedMessage, event.getReaction(), userInAServer);
});
} catch (Exception e) {
log.warn("Exception on reaction added handler:", e);
if(!featureFlagService.isFeatureEnabled(reactedAddedListener.getFeature(), event.getGuild().getIdLong())) {
return;
}
try {
reactedAddedListener.executeReactionAdded(cachedMessage, event.getReaction(), userInAServer);
} catch (AbstractoRunTimeException e) {
log.warn(String.format("Failed to execute reaction added listener %s.", reactedAddedListener.getClass().getName()), e);
}
});
}
@Override
@@ -120,7 +127,14 @@ public class ReactionUpdatedListener extends ListenerAdapter {
AUserInAServer userInAServer = userManagementService.loadUser(event.getGuild().getIdLong(), event.getUserIdLong());
removeReactionIfThere(cachedMessage, reaction, userInAServer.getUserReference());
reactionRemovedListener.forEach(reactedAddedListener -> {
if(!featureFlagService.isFeatureEnabled(reactedAddedListener.getFeature(), event.getGuild().getIdLong())) {
return;
}
try {
reactedAddedListener.executeReactionRemoved(cachedMessage, event.getReaction(), userInAServer);
} catch (AbstractoRunTimeException e) {
log.warn(String.format("Failed to execute reaction removed listener %s.", reactedAddedListener.getClass().getName()), e);
}
});
}

View File

@@ -0,0 +1,9 @@
package dev.sheldan.abstracto.repository;
import dev.sheldan.abstracto.core.models.database.AFeatureFlag;
import dev.sheldan.abstracto.core.models.database.AServer;
import org.springframework.data.jpa.repository.JpaRepository;
public interface FeatureFlagRepository extends JpaRepository<AFeatureFlag, Long> {
AFeatureFlag findByServerAndKey(AServer server, String key);
}

View File

@@ -1,5 +1,6 @@
package dev.sheldan.abstracto.repository;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.core.models.database.PostTarget;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@@ -7,6 +8,6 @@ import org.springframework.stereotype.Repository;
@Repository
public interface PostTargetRepository extends JpaRepository<PostTarget, Long> {
PostTarget findPostTargetByName(String name);
PostTarget findPostTargetByNameAndServerReference(String name, AServer server);
}

View File

@@ -0,0 +1,12 @@
package dev.sheldan.abstracto.core.exception;
public class AbstractoRunTimeException extends RuntimeException {
public AbstractoRunTimeException(String message) {
super(message);
}
public AbstractoRunTimeException(String message, Throwable cause) {
super(message, cause);
}
}

View File

@@ -0,0 +1,7 @@
package dev.sheldan.abstracto.core.exception;
public class ChannelException extends AbstractoRunTimeException {
public ChannelException(String message) {
super(message);
}
}

View File

@@ -1,6 +1,6 @@
package dev.sheldan.abstracto.core.exception;
public class ConfigurationException extends RuntimeException {
public class ConfigurationException extends Exception {
public ConfigurationException(String message) {
super(message);
}

View File

@@ -0,0 +1,7 @@
package dev.sheldan.abstracto.core.exception;
public class EmoteException extends AbstractoRunTimeException {
public EmoteException(String message) {
super(message);
}
}

View File

@@ -0,0 +1,7 @@
package dev.sheldan.abstracto.core.exception;
public class FeatureDisabledException extends AbstractoRunTimeException {
public FeatureDisabledException(String message) {
super(message);
}
}

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