added message to user initiated context

fixed templates for ban and kick logging
refactored kicking service
fixed guild not found exception template
added command validator to be used for unit testing commands
added default values for command configuration
changed some interfaces to message channel instead of text channel
added separate executor service for un-mutes, which is shared
updated spring boot version to 2.3.1
removed database connection string from properties
added logback configuration
changed some future logic in purge
refactored error message for un mute, when there is no active mute
refactored listener interface and removed usage of context utils
added tests for moderation services
This commit is contained in:
Sheldan
2020-06-20 11:08:44 +02:00
parent 8acd4f818d
commit c44eb80fc5
140 changed files with 4176 additions and 225 deletions

View File

@@ -24,6 +24,7 @@ import java.util.List;
@Slf4j
public class Ban extends AbstractConditionableCommand {
public static final String BAN_DEFAULT_REASON_TEMPLATE = "ban_default_reason";
@Autowired
private BanService banService;
@@ -32,9 +33,10 @@ public class Ban extends AbstractConditionableCommand {
@Override
public CommandResult execute(CommandContext commandContext) {
checkParameters(commandContext);
List<Object> parameters = commandContext.getParameters().getParameters();
Member member = (Member) parameters.get(0);
String defaultReason = templateService.renderTemplateWithMap("ban_default_reason", null);
String defaultReason = templateService.renderSimpleTemplate(BAN_DEFAULT_REASON_TEMPLATE);
String reason = parameters.size() == 2 ? (String) parameters.get(1) : defaultReason;
BanLog banLogModel = (BanLog) ContextConverter.fromCommandContext(commandContext, BanLog.class);

View File

@@ -28,15 +28,16 @@ public class BanId extends AbstractConditionableCommand {
@Override
public CommandResult execute(CommandContext commandContext) {
checkParameters(commandContext);
List<Object> parameters = commandContext.getParameters().getParameters();
Long userId = (Long) parameters.get(0);
String defaultReason = templateService.renderTemplateWithMap("ban_default_reason", null);
String defaultReason = templateService.renderSimpleTemplate(Ban.BAN_DEFAULT_REASON_TEMPLATE);
String reason = parameters.size() == 2 ? (String) parameters.get(1) : defaultReason;
BanIdLog banLogModel = (BanIdLog) ContextConverter.fromCommandContext(commandContext, BanIdLog.class);
banLogModel.setBannedUserId(userId);
banLogModel.setBanningUser(commandContext.getAuthor());
banLogModel.setReason(reason);
banService.banMember(userId, commandContext.getGuild().getIdLong(), reason, banLogModel);
banService.banMember(commandContext.getGuild().getIdLong(), userId, reason, banLogModel);
return CommandResult.fromSuccess();
}

View File

@@ -24,6 +24,7 @@ public class DecayAllWarnings extends AbstractConditionableCommand {
@Override
public CommandResult execute(CommandContext commandContext) {
checkParameters(commandContext);
List<Object> parameters = commandContext.getParameters().getParameters();
boolean logWarnings = !parameters.isEmpty() ? (Boolean) parameters.get(0) : Boolean.FALSE;
warnService.decayAllWarningsForServer(commandContext.getUserInitiatedContext().getServer(), logWarnings);

View File

@@ -20,6 +20,7 @@ import java.util.List;
@Component
public class DeleteNote extends AbstractConditionableCommand {
public static final String NOTE_NOT_FOUND_EXCEPTION_TEMPLATE = "note_not_found_exception";
@Autowired
private UserNoteManagementService userNoteManagementService;
@@ -28,11 +29,12 @@ public class DeleteNote extends AbstractConditionableCommand {
@Override
public CommandResult execute(CommandContext commandContext) {
checkParameters(commandContext);
Long id = (Long) commandContext.getParameters().getParameters().get(0);
if(userNoteManagementService.noteExists(id)) {
userNoteManagementService.deleteNote(id);
} else {
return CommandResult.fromError(templateService.renderSimpleTemplate("note_not_found_exception"));
return CommandResult.fromError(templateService.renderSimpleTemplate(NOTE_NOT_FOUND_EXCEPTION_TEMPLATE));
}
return CommandResult.fromSuccess();
}

View File

@@ -27,6 +27,7 @@ public class DeleteWarning extends AbstractConditionableCommand {
@Override
public CommandResult execute(CommandContext commandContext) {
checkParameters(commandContext);
Long warnId = (Long) commandContext.getParameters().getParameters().get(0);
Optional<Warning> optional = warnManagementService.findById(warnId);
optional.ifPresent(warning -> {

View File

@@ -22,6 +22,7 @@ import java.util.List;
@Component
public class Kick extends AbstractConditionableCommand {
public static final String KICK_DEFAULT_REASON_TEMPLATE = "kick_default_reason";
@Autowired
private TemplateService templateService;
@@ -30,10 +31,10 @@ public class Kick extends AbstractConditionableCommand {
@Override
public CommandResult execute(CommandContext commandContext) {
checkParameters(commandContext);
List<Object> parameters = commandContext.getParameters().getParameters();
Member member = (Member) parameters.get(0);
String defaultReason = templateService.renderTemplateWithMap("ban_default_reason", null);
String defaultReason = templateService.renderSimpleTemplate(KICK_DEFAULT_REASON_TEMPLATE);
String reason = parameters.size() == 2 ? (String) parameters.get(1) : defaultReason;
KickLogModel kickLogModel = (KickLogModel) ContextConverter.fromCommandContext(commandContext, KickLogModel.class);

View File

@@ -9,10 +9,8 @@ import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.command.execution.ContextConverter;
import dev.sheldan.abstracto.core.config.FeatureEnum;
import dev.sheldan.abstracto.core.service.ChannelService;
import dev.sheldan.abstracto.core.service.FeatureFlagService;
import dev.sheldan.abstracto.moderation.config.ModerationModule;
import dev.sheldan.abstracto.moderation.config.features.ModerationFeatures;
import dev.sheldan.abstracto.moderation.config.features.WarningDecayFeature;
import dev.sheldan.abstracto.moderation.models.template.commands.MyWarningsModel;
import dev.sheldan.abstracto.moderation.service.management.WarnManagementService;
import org.springframework.beans.factory.annotation.Autowired;
@@ -25,18 +23,13 @@ import java.util.List;
@Component
public class MyWarnings extends AbstractConditionableCommand {
public static final String MY_WARNINGS_RESPONSE_EMBED_TEMPLATE = "myWarnings_response";
@Autowired
private ChannelService channelService;
@Autowired
private WarnManagementService warnManagementService;
@Autowired
private FeatureFlagService featureFlagService;
@Autowired
private WarningDecayFeature warningDecayFeature;
@Override
public CommandResult execute(CommandContext commandContext) {
MyWarningsModel model = (MyWarningsModel) ContextConverter.fromCommandContext(commandContext, MyWarningsModel.class);
@@ -44,7 +37,7 @@ public class MyWarnings extends AbstractConditionableCommand {
model.setCurrentWarnCount(currentWarnCount);
Long totalWarnCount = warnManagementService.getTotalWarnsForUser(commandContext.getUserInitiatedContext().getAUserInAServer());
model.setTotalWarnCount(totalWarnCount);
channelService.sendEmbedTemplateInChannel("myWarnings_response", model, commandContext.getChannel());
channelService.sendEmbedTemplateInChannel(MY_WARNINGS_RESPONSE_EMBED_TEMPLATE, model, commandContext.getChannel());
return CommandResult.fromSuccess();
}

View File

@@ -34,6 +34,7 @@ public class Purge extends AbstractConditionableCommand {
@Override
public CommandResult execute(CommandContext commandContext) {
checkParameters(commandContext);
Integer amountOfMessages = (Integer) commandContext.getParameters().getParameters().get(0);
Member memberToPurgeMessagesOf = null;
if(commandContext.getParameters().getParameters().size() == 2) {

View File

@@ -27,6 +27,7 @@ public class SlowMode extends AbstractConditionableCommand {
@Override
public CommandResult execute(CommandContext commandContext) {
checkParameters(commandContext);
TextChannel channel;
String durationString = (String) commandContext.getParameters().getParameters().get(0);
Duration duration;

View File

@@ -30,6 +30,7 @@ public class UserNoteCommand extends AbstractConditionableCommand {
@Override
public CommandResult execute(CommandContext commandContext) {
checkParameters(commandContext);
List<Object> parameters = commandContext.getParameters().getParameters();
Member member = (Member) parameters.get(0);
String text = (String) parameters.get(1);

View File

@@ -28,6 +28,7 @@ import java.util.List;
@Component
public class UserNotes extends AbstractConditionableCommand {
public static final String USER_NOTES_RESPONSE_TEMPLATE = "user_notes_response";
@Autowired
private UserNoteManagementService userNoteManagementService;
@@ -45,6 +46,7 @@ public class UserNotes extends AbstractConditionableCommand {
@Override
public CommandResult execute(CommandContext commandContext) {
checkParameters(commandContext);
List<Object> parameters = commandContext.getParameters().getParameters();
List<UserNote> userNotes;
@@ -63,7 +65,7 @@ public class UserNotes extends AbstractConditionableCommand {
userNotes = userNoteManagementService.loadNotesForServer(commandContext.getUserInitiatedContext().getServer());
}
model.setUserNotes(userNotesConverter.fromNotes(userNotes));
channelService.sendEmbedTemplateInChannel("user_notes_response", model, commandContext.getChannel());
channelService.sendEmbedTemplateInChannel(USER_NOTES_RESPONSE_TEMPLATE, model, commandContext.getChannel());
return CommandResult.fromSuccess();
}

View File

@@ -24,6 +24,7 @@ import java.util.List;
@Slf4j
public class Warn extends AbstractConditionableCommand {
public static final String WARN_DEFAULT_REASON_TEMPLATE = "warn_default_reason";
@Autowired
private WarnService warnService;
@@ -32,9 +33,10 @@ public class Warn extends AbstractConditionableCommand {
@Override
public CommandResult execute(CommandContext commandContext) {
checkParameters(commandContext);
List<Object> parameters = commandContext.getParameters().getParameters();
Member member = (Member) parameters.get(0);
String defaultReason = templateService.renderTemplateWithMap("warn_default_reason", null);
String defaultReason = templateService.renderSimpleTemplate(WARN_DEFAULT_REASON_TEMPLATE);
String reason = parameters.size() == 2 ? (String) parameters.get(1) : defaultReason;
WarnLog warnLogModel = (WarnLog) ContextConverter.fromCommandContext(commandContext, WarnLog.class);
warnLogModel.setWarnedUser(member);

View File

@@ -10,7 +10,6 @@ import dev.sheldan.abstracto.core.command.execution.CommandContext;
import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.command.execution.ContextConverter;
import dev.sheldan.abstracto.core.config.FeatureEnum;
import dev.sheldan.abstracto.core.service.BotService;
import dev.sheldan.abstracto.core.service.PaginatorService;
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
import dev.sheldan.abstracto.moderation.config.ModerationModule;
@@ -20,7 +19,6 @@ import dev.sheldan.abstracto.moderation.models.database.Warning;
import dev.sheldan.abstracto.moderation.models.template.commands.WarnEntry;
import dev.sheldan.abstracto.moderation.models.template.commands.WarningsModel;
import dev.sheldan.abstracto.moderation.service.management.WarnManagementService;
import dev.sheldan.abstracto.templating.service.TemplateService;
import net.dv8tion.jda.api.entities.Member;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@@ -31,15 +29,10 @@ import java.util.List;
@Component
public class Warnings extends AbstractConditionableCommand {
@Autowired
private BotService botService;
public static final String WARNINGS_RESPONSE_TEMPLATE = "warnings_response";
@Autowired
private WarnManagementService warnManagementService;
@Autowired
private TemplateService templateService;
@Autowired
private UserInServerManagementService userInServerManagementService;
@@ -54,6 +47,7 @@ public class Warnings extends AbstractConditionableCommand {
@Override
public CommandResult execute(CommandContext commandContext) {
checkParameters(commandContext);
List<Warning> warnsToDisplay;
if(!commandContext.getParameters().getParameters().isEmpty()) {
Member member = (Member) commandContext.getParameters().getParameters().get(0);
@@ -66,7 +60,7 @@ public class Warnings extends AbstractConditionableCommand {
WarningsModel model = (WarningsModel) ContextConverter.fromCommandContext(commandContext, WarningsModel.class);
model.setWarnings(warnEntries);
Paginator paginator = paginatorService.createPaginatorFromTemplate("warnings_response", model, eventWaiter);
Paginator paginator = paginatorService.createPaginatorFromTemplate(WARNINGS_RESPONSE_TEMPLATE, model, eventWaiter);
paginator.display(commandContext.getChannel());
return CommandResult.fromSuccess();
}
@@ -74,7 +68,7 @@ public class Warnings extends AbstractConditionableCommand {
@Override
public CommandConfiguration getConfiguration() {
List<Parameter> parameters = new ArrayList<>();
parameters.add(Parameter.builder().name("user").type(Member.class).optional(true).build());
parameters.add(Parameter.builder().name("user").type(Member.class).templated(true).optional(true).build());
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();
return CommandConfiguration.builder()
.name("warnings")

View File

@@ -30,6 +30,7 @@ public class Mute extends AbstractConditionableCommand {
@Override
public CommandResult execute(CommandContext commandContext) {
checkParameters(commandContext);
List<Object> parameters = commandContext.getParameters().getParameters();
Member member = (Member) parameters.get(0);
Duration duration = (Duration) parameters.get(1);

View File

@@ -25,6 +25,7 @@ public class SetMuteRole extends AbstractConditionableCommand {
@Override
public CommandResult execute(CommandContext commandContext) {
checkParameters(commandContext);
ARole role = (ARole) commandContext.getParameters().getParameters().get(0);
muteRoleManagementService.setMuteRoleForServer(commandContext.getUserInitiatedContext().getServer(), role);
return CommandResult.fromSuccess();

View File

@@ -9,10 +9,10 @@ import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.config.FeatureEnum;
import dev.sheldan.abstracto.moderation.config.ModerationModule;
import dev.sheldan.abstracto.moderation.config.features.ModerationFeatures;
import dev.sheldan.abstracto.moderation.exception.MuteException;
import dev.sheldan.abstracto.moderation.models.database.Mute;
import dev.sheldan.abstracto.moderation.service.MuteService;
import dev.sheldan.abstracto.moderation.service.management.MuteManagementService;
import dev.sheldan.abstracto.templating.service.TemplateService;
import net.dv8tion.jda.api.entities.Member;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@@ -23,30 +23,35 @@ import java.util.List;
@Component
public class UnMute extends AbstractConditionableCommand {
public static final String NO_ACTIVE_MUTE = "unMute_has_no_active_mute";
@Autowired
private MuteService muteService;
@Autowired
private MuteManagementService muteManagementService;
@Autowired
private TemplateService templateService;
@Override
public CommandResult execute(CommandContext commandContext) {
checkParameters(commandContext);
List<Object> parameters = commandContext.getParameters().getParameters();
Member member = (Member) parameters.get(0);
Mute mute = muteManagementService.getAMuteOf(member);
if(mute == null) {
throw new MuteException("User has no active mutes");
if(!muteManagementService.hasActiveMute(member)) {
return CommandResult.fromError(templateService.renderSimpleTemplate(NO_ACTIVE_MUTE));
}
Mute mute = muteManagementService.getAMuteOf(member);
muteService.unmuteUser(mute);
muteService.cancelUnmuteJob(mute);
muteService.completelyUnmuteUser(member);
muteService.completelyUnMuteMember(member);
return CommandResult.fromSuccess();
}
@Override
public CommandConfiguration getConfiguration() {
List<Parameter> parameters = new ArrayList<>();
parameters.add(Parameter.builder().name("user").type(Member.class).build());
parameters.add(Parameter.builder().name("user").type(Member.class).templated(true).build());
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();
return CommandConfiguration.builder()
.name("unMute")

View File

@@ -0,0 +1,17 @@
package dev.sheldan.abstracto.moderation.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
@Configuration
public class ModerationSpringConfig {
@Bean(name = "unmuteScheduler")
public ScheduledExecutorService getUnMuteExecutor() {
return Executors.newScheduledThreadPool(1);
}
}

View File

@@ -2,7 +2,6 @@ package dev.sheldan.abstracto.moderation.converter;
import dev.sheldan.abstracto.core.models.FullUser;
import dev.sheldan.abstracto.core.service.BotService;
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
import dev.sheldan.abstracto.moderation.models.database.Warning;
import dev.sheldan.abstracto.moderation.models.template.commands.WarnEntry;
import org.springframework.beans.factory.annotation.Autowired;
@@ -14,9 +13,6 @@ import java.util.List;
@Component
public class WarnEntryConverter {
@Autowired
private UserInServerManagementService userInServerManagementService;
@Autowired
private BotService botService;

View File

@@ -2,7 +2,6 @@ package dev.sheldan.abstracto.moderation.job;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.core.service.FeatureFlagService;
import dev.sheldan.abstracto.core.service.management.FeatureFlagManagementService;
import dev.sheldan.abstracto.core.service.management.ServerManagementService;
import dev.sheldan.abstracto.moderation.config.features.WarningDecayFeature;
import dev.sheldan.abstracto.moderation.service.WarnService;
@@ -27,9 +26,6 @@ public class WarnDecayJob extends QuartzJobBean {
@Autowired
private ServerManagementService serverManagementService;
@Autowired
private FeatureFlagManagementService featureFlagManagementService;
@Autowired
private FeatureFlagService featureFlagService;

View File

@@ -11,18 +11,16 @@ 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";
public static final String USER_JOIN_TEMPLATE = "user_join";
@Autowired
private TemplateService templateService;
@@ -31,8 +29,7 @@ public class JoinLogger implements JoinListener {
private PostTargetService postTargetService;
@NotNull
private HashMap<String, Object> getUserParameter(@Nonnull User user) {
private HashMap<String, Object> getUserParameter(User user) {
HashMap<String, Object> parameters = new HashMap<>();
parameters.put("user", user);
return parameters;

View File

@@ -21,7 +21,7 @@ import java.util.HashMap;
@Slf4j
public class LeaveLogger implements LeaveListener {
private static final String USER_LEAVE_TEMPLATE = "user_leave";
public static final String USER_LEAVE_TEMPLATE = "user_leave";
@Autowired
private TemplateService templateService;

View File

@@ -2,6 +2,8 @@ package dev.sheldan.abstracto.moderation.listener;
import dev.sheldan.abstracto.core.config.FeatureEnum;
import dev.sheldan.abstracto.core.listener.MessageDeletedListener;
import dev.sheldan.abstracto.core.models.AServerAChannelAUser;
import dev.sheldan.abstracto.core.models.GuildChannelMember;
import dev.sheldan.abstracto.core.models.cache.CachedMessage;
import dev.sheldan.abstracto.moderation.config.features.ModerationFeatures;
import dev.sheldan.abstracto.moderation.config.posttargets.LoggingPostTarget;
@@ -19,8 +21,8 @@ import org.springframework.stereotype.Component;
@Slf4j
public class MessageDeleteLogListener implements MessageDeletedListener {
private static final String MESSAGE_DELETED_TEMPLATE = "message_deleted";
private static final String MESSAGE_DELETED_ATTACHMENT_TEMPLATE = "message_deleted_attachment";
public static final String MESSAGE_DELETED_TEMPLATE = "message_deleted";
public static final String MESSAGE_DELETED_ATTACHMENT_TEMPLATE = "message_deleted_attachment";
@Autowired
private ContextUtils contextUtils;
@@ -32,18 +34,38 @@ public class MessageDeleteLogListener implements MessageDeletedListener {
private PostTargetService postTargetService;
@Override
public void execute(CachedMessage messageFromCache) {
public void execute(CachedMessage messageFromCache, AServerAChannelAUser authorUser, GuildChannelMember authorMember) {
log.trace("Message {} in channel {} in guild {} was deleted.", messageFromCache.getMessageId(), messageFromCache.getChannelId(), messageFromCache.getServerId());
MessageDeletedLog logModel = (MessageDeletedLog) contextUtils.fromMessage(messageFromCache, MessageDeletedLog.class);
logModel.setMessage(messageFromCache);
MessageDeletedLog logModel = MessageDeletedLog
.builder()
.cachedMessage(messageFromCache)
.server(authorUser.getGuild())
.channel(authorUser.getChannel())
.user(authorUser.getUser())
.aUserInAServer(authorUser.getAUserInAServer())
.guild(authorMember.getGuild())
.messageChannel(authorMember.getTextChannel())
.member(authorMember.getMember())
.build();
MessageToSend message = templateService.renderEmbedTemplate(MESSAGE_DELETED_TEMPLATE, logModel);
postTargetService.sendEmbedInPostTarget(message, LoggingPostTarget.DELETE_LOG, messageFromCache.getServerId());
for (int i = 0; i < messageFromCache.getAttachmentUrls().size(); i++) {
MessageDeletedAttachmentLog log = (MessageDeletedAttachmentLog) contextUtils.fromMessage(messageFromCache, MessageDeletedAttachmentLog.class);
log.setImageUrl(messageFromCache.getAttachmentUrls().get(i));
log.setCounter(i + 1);
MessageToSend attachmentEmbed = templateService.renderEmbedTemplate(MESSAGE_DELETED_ATTACHMENT_TEMPLATE, log);
postTargetService.sendEmbedInPostTarget(attachmentEmbed, LoggingPostTarget.DELETE_LOG, messageFromCache.getServerId());
if(messageFromCache.getAttachmentUrls() != null){
for (int i = 0; i < messageFromCache.getAttachmentUrls().size(); i++) {
MessageDeletedAttachmentLog log = MessageDeletedAttachmentLog
.builder()
.imageUrl(messageFromCache.getAttachmentUrls().get(i))
.counter(i + 1)
.server(authorUser.getGuild())
.channel(authorUser.getChannel())
.user(authorUser.getUser())
.aUserInAServer(authorUser.getAUserInAServer())
.guild(authorMember.getGuild())
.messageChannel(authorMember.getTextChannel())
.member(authorMember.getMember())
.build();
MessageToSend attachmentEmbed = templateService.renderEmbedTemplate(MESSAGE_DELETED_ATTACHMENT_TEMPLATE, log);
postTargetService.sendEmbedInPostTarget(attachmentEmbed, LoggingPostTarget.DELETE_LOG, messageFromCache.getServerId());
}
}
}

View File

@@ -19,7 +19,7 @@ import org.springframework.transaction.annotation.Transactional;
@Slf4j
public class MessageEditedListener implements MessageTextUpdatedListener {
private static final String MESSAGE_EDITED_TEMPLATE = "message_edited";
public static final String MESSAGE_EDITED_TEMPLATE = "message_edited";
@Autowired
private TemplateService templateService;
@@ -35,13 +35,14 @@ public class MessageEditedListener implements MessageTextUpdatedListener {
return;
}
log.trace("Message {} in channel {} in guild {} was edited.", messageBefore.getMessageId(), messageBefore.getChannelId(), messageBefore.getServerId());
MessageEditedLog log = MessageEditedLog.
builder().
messageAfter(messageAfter)
MessageEditedLog log = MessageEditedLog
.builder()
.messageAfter(messageAfter)
.messageBefore(messageBefore)
.messageChannel(messageAfter.getTextChannel())
.guild(messageAfter.getGuild())
.member(messageAfter.getMember()).build();
.member(messageAfter.getMember())
.build();
MessageToSend message = templateService.renderEmbedTemplate(MESSAGE_EDITED_TEMPLATE, log);
postTargetService.sendEmbedInPostTarget(message, LoggingPostTarget.EDIT_LOG, messageBefore.getServerId());
}

View File

@@ -1,6 +1,7 @@
package dev.sheldan.abstracto.moderation.listener;
import dev.sheldan.abstracto.core.service.management.DefaultConfigManagementService;
import dev.sheldan.abstracto.moderation.config.features.WarningDecayFeature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.event.ContextRefreshedEvent;
@@ -20,6 +21,6 @@ public class ModerationDefaultConfigListener {
@EventListener
@Transactional
public void handleContextRefreshEvent(ContextRefreshedEvent ctxStartEvt) {
defaultConfigManagementService.createDefaultConfig("decayDays", decayDays);
defaultConfigManagementService.createDefaultConfig(WarningDecayFeature.DECAY_DAYS_KEY, decayDays);
}
}

View File

@@ -17,4 +17,6 @@ public interface MuteRoleRepository extends JpaRepository<MuteRole, Long> {
@QueryHints(@QueryHint(name = org.hibernate.annotations.QueryHints.CACHEABLE, value = "true"))
List<MuteRole> findAllByRoleServer(AServer server);
boolean existsByRoleServer(AServer server);
}

View File

@@ -5,6 +5,7 @@ import dev.sheldan.abstracto.core.models.context.ServerContext;
import dev.sheldan.abstracto.core.service.BotService;
import dev.sheldan.abstracto.core.service.PostTargetService;
import dev.sheldan.abstracto.moderation.config.posttargets.ModerationPostTarget;
import dev.sheldan.abstracto.templating.model.MessageToSend;
import dev.sheldan.abstracto.templating.service.TemplateService;
import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.entities.Guild;
@@ -18,8 +19,9 @@ import java.util.Optional;
@Slf4j
public class BanServiceBean implements BanService {
private static final String BAN_LOG_TEMPLATE = "ban_log";
private static final String BAN_ID_LOG_TEMPLATE = "banid_log";
public static final String BAN_LOG_TEMPLATE = "ban_log";
public static final String BAN_ID_LOG_TEMPLATE = "banId_log";
@Autowired
private BotService botService;
@@ -31,26 +33,30 @@ public class BanServiceBean implements BanService {
@Override
public void banMember(Member member, String reason, ServerContext banLog) {
this.banUser(member.getGuild().getIdLong(), member.getIdLong(), reason);
String warnLogMessage = templateService.renderTemplate(BAN_LOG_TEMPLATE, banLog);
postTargetService.sendTextInPostTarget(warnLogMessage, ModerationPostTarget.BAN_LOG, banLog.getServer().getId());
this.banUser(member.getGuild(), member.getIdLong(), reason);
MessageToSend banLogMessage = templateService.renderEmbedTemplate(BAN_LOG_TEMPLATE, banLog);
postTargetService.sendEmbedInPostTarget(banLogMessage, ModerationPostTarget.BAN_LOG, member.getGuild().getIdLong());
}
@Override
public void banMember(Long guildId, Long userId, String reason, ServerContext banIdLog) {
banUser(guildId, userId, reason);
String warnLogMessage = templateService.renderTemplate(BAN_ID_LOG_TEMPLATE, banIdLog);
postTargetService.sendTextInPostTarget(warnLogMessage, ModerationPostTarget.BAN_LOG, guildId);
MessageToSend banLogMessage = templateService.renderEmbedTemplate(BAN_ID_LOG_TEMPLATE, banIdLog);
postTargetService.sendEmbedInPostTarget(banLogMessage, ModerationPostTarget.BAN_LOG, guildId);
}
private void banUser(Long guildId, Long userId, String reason) {
Optional<Guild> guildByIdOptional = botService.getGuildById(guildId);
if(guildByIdOptional.isPresent()) {
log.info("Banning user {} in guild {}.", userId, guildId);
guildByIdOptional.get().ban(userId.toString(), 0, reason).queue();
banUser(guildByIdOptional.get(), userId, reason);
} else {
log.warn("Guild {} not found. Not able to ban user {}", guildId, userId);
throw new GuildException(guildId);
}
}
private void banUser(Guild guild, Long userId, String reason) {
guild.ban(userId.toString(), 0, reason).queue();
}
}

View File

@@ -1,10 +1,9 @@
package dev.sheldan.abstracto.moderation.service;
import dev.sheldan.abstracto.core.exception.GuildException;
import dev.sheldan.abstracto.core.service.BotService;
import dev.sheldan.abstracto.core.service.PostTargetService;
import dev.sheldan.abstracto.moderation.config.posttargets.ModerationPostTarget;
import dev.sheldan.abstracto.moderation.models.template.commands.KickLogModel;
import dev.sheldan.abstracto.templating.model.MessageToSend;
import dev.sheldan.abstracto.templating.service.TemplateService;
import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.entities.Guild;
@@ -12,15 +11,11 @@ import net.dv8tion.jda.api.entities.Member;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Optional;
@Component
@Slf4j
public class KickServiceBean implements KickService {
private static final String KICK_LOG_TEMPLATE = "kick_log";
@Autowired
private BotService botService;
public static final String KICK_LOG_TEMPLATE = "kick_log";
@Autowired
private TemplateService templateService;
@@ -30,19 +25,14 @@ public class KickServiceBean implements KickService {
@Override
public void kickMember(Member member, String reason, KickLogModel kickLogModel) {
Optional<Guild> guildById = botService.getGuildById(kickLogModel.getGuild().getIdLong());
log.info("Kicking user {} from guild {}", member.getUser().getIdLong(), member.getGuild().getIdLong());
if(guildById.isPresent()) {
guildById.get().kick(member, reason).queue();
this.sendKickLog(kickLogModel);
} else {
log.warn("Not able to kick. Guild {} not found.", kickLogModel.getGuild().getIdLong());
throw new GuildException(kickLogModel.getGuild().getIdLong());
}
Guild guild = member.getGuild();
log.info("Kicking user {} from guild {}", member.getUser().getIdLong(), guild.getIdLong());
guild.kick(member, reason).queue();
this.sendKickLog(kickLogModel);
}
private void sendKickLog(KickLogModel kickLogModel) {
String warnLogMessage = templateService.renderTemplate(KICK_LOG_TEMPLATE, kickLogModel);
postTargetService.sendTextInPostTarget(warnLogMessage, ModerationPostTarget.KICK_LOG, kickLogModel.getServer().getId());
MessageToSend warnLogMessage = templateService.renderEmbedTemplate(KICK_LOG_TEMPLATE, kickLogModel);
postTargetService.sendEmbedInPostTarget(warnLogMessage, ModerationPostTarget.KICK_LOG, kickLogModel.getServer().getId());
}
}

View File

@@ -1,6 +1,5 @@
package dev.sheldan.abstracto.moderation.service;
import dev.sheldan.abstracto.core.exception.AbstractoRunTimeException;
import dev.sheldan.abstracto.core.exception.ChannelNotFoundException;
import dev.sheldan.abstracto.core.models.AServerAChannelMessage;
import dev.sheldan.abstracto.core.models.FullUser;
@@ -23,12 +22,10 @@ import dev.sheldan.abstracto.scheduling.service.SchedulerService;
import dev.sheldan.abstracto.templating.model.MessageToSend;
import dev.sheldan.abstracto.templating.service.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.Message;
import net.dv8tion.jda.api.entities.TextChannel;
import net.dv8tion.jda.api.entities.*;
import org.quartz.JobDataMap;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
@@ -37,7 +34,6 @@ import java.time.Instant;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
@@ -75,18 +71,22 @@ public class MuteServiceBean implements MuteService {
@Autowired
private MuteService self;
@Autowired
@Qualifier("unmuteScheduler")
private ScheduledExecutorService unMuteScheduler;
@Autowired
private ChannelManagementService channelManagementService;
private static final String MUTE_LOG_TEMPLATE = "mute_log";
private static final String UNMUTE_LOG_TEMPLATE = "unmute_log";
private static final String MUTE_NOTIFICATION_TEMPLATE = "mute_notification";
public static final String MUTE_LOG_TEMPLATE = "mute_log";
public static final String UNMUTE_LOG_TEMPLATE = "unmute_log";
public static final String MUTE_NOTIFICATION_TEMPLATE = "mute_notification";
@Override
public Mute muteMember(Member memberToMute, Member mutingMember, String reason, Instant unmuteDate, Message message) {
FullUser mutedUser = FullUser
.builder()
.aUserInAServer(userInServerManagementService.loadUser(memberToMute))
.aUserInAServer(userInServerManagementService.loadUser(memberToMute))
.member(memberToMute)
.build();
@@ -99,7 +99,7 @@ public class MuteServiceBean implements MuteService {
}
@Override
public Mute muteMember(AUserInAServer userBeingMuted, AUserInAServer userMuting, String reason, Instant unmuteDate, Message message) {
public Mute muteAUserInAServer(AUserInAServer userBeingMuted, AUserInAServer userMuting, String reason, Instant unmuteDate, Message message) {
FullUser mutedUser = FullUser
.builder()
.aUserInAServer(userBeingMuted)
@@ -116,20 +116,44 @@ public class MuteServiceBean implements MuteService {
@Override
public Mute muteUser(FullUser userBeingMuted, FullUser userMuting, String reason, Instant unmuteDate, Message message) {
AServer serverBeingMutedIn = userBeingMuted.getAUserInAServer().getServerReference();
if(!muteRoleManagementService.muteRoleForServerExists(serverBeingMutedIn)) {
log.error("Mute role for server {} has not been setup.", serverBeingMutedIn.getId());
throw new MuteException("Mute role for server has not been setup");
}
Member memberBeingMuted = userBeingMuted.getMember();
log.info("User {} mutes {} until {}",
log.info("User {} mutes user {} until {}",
memberBeingMuted.getIdLong(), userMuting.getMember().getIdLong(), unmuteDate);
if(message != null) {
log.trace("because of message {} in channel {} in server {}", message.getId(), message.getChannel().getId(), message.getGuild().getId());
} else {
log.trace("This mute was not triggered by a message.");
}
if(!muteRoleManagementService.muteRoleForServerExists(userBeingMuted.getAUserInAServer().getServerReference())) {
log.error("Mute role for server {} has not been setup.", userBeingMuted.getAUserInAServer().getServerReference().getId());
throw new MuteException("Mute role for server has not been setup");
}
AUserInAServer userInServerBeingMuted = userBeingMuted.getAUserInAServer();
applyMuteRole(userInServerBeingMuted);
Mute mute = createMuteObject(userMuting, reason, unmuteDate, message, userInServerBeingMuted);
Guild guild = memberBeingMuted.getGuild();
if(memberBeingMuted.getVoiceState() != null && memberBeingMuted.getVoiceState().getChannel() != null) {
guild.kickVoiceMember(memberBeingMuted).queue();
}
sendMuteNotification(message, memberBeingMuted, mute, guild);
String triggerKey = startUnmuteJobFor(unmuteDate, mute);
mute.setTriggerKey(triggerKey);
muteManagementService.saveMute(mute);
return mute;
}
private void sendMuteNotification(Message message, Member memberBeingMuted, Mute mute, Guild guild) {
log.trace("Notifying the user about the mute.");
MuteNotification muteNotification = MuteNotification.builder().mute(mute).serverName(guild.getName()).build();
String muteNotificationMessage = templateService.renderTemplate(MUTE_NOTIFICATION_TEMPLATE, muteNotification);
MessageChannel textChannel = message != null ? message.getChannel() : null;
messageService.sendMessageToUser(memberBeingMuted.getUser(), muteNotificationMessage, textChannel);
}
private Mute createMuteObject(FullUser userMuting, String reason, Instant unmuteDate, Message message, AUserInAServer userInServerBeingMuted) {
AServerAChannelMessage origin = null;
if(message != null) {
long channelId = message.getChannel().getIdLong();
@@ -142,21 +166,7 @@ public class MuteServiceBean implements MuteService {
.messageId(message.getIdLong())
.build();
}
Mute mute = muteManagementService.createMute(userInServerBeingMuted, userMuting.getAUserInAServer(), reason, unmuteDate, origin);
Guild guild = memberBeingMuted.getGuild();
if(memberBeingMuted.getVoiceState() != null && memberBeingMuted.getVoiceState().getChannel() != null) {
guild.kickVoiceMember(memberBeingMuted).queue();
}
log.trace("Notifying the user about the mute.");
MuteNotification muteNotification = MuteNotification.builder().mute(mute).serverName(guild.getName()).build();
String muteNotificationMessage = templateService.renderTemplate(MUTE_NOTIFICATION_TEMPLATE, muteNotification);
TextChannel textChannel = message != null ? message.getTextChannel() : null;
messageService.sendMessageToUser(memberBeingMuted.getUser(), muteNotificationMessage, textChannel);
String triggerKey = startUnmuteJobFor(unmuteDate, mute);
mute.setTriggerKey(triggerKey);
muteManagementService.saveMute(mute);
return mute;
return muteManagementService.createMute(userInServerBeingMuted, userMuting.getAUserInAServer(), reason, unmuteDate, origin);
}
@Override
@@ -170,10 +180,9 @@ public class MuteServiceBean implements MuteService {
Duration muteDuration = Duration.between(Instant.now(), unmuteDate);
if(muteDuration.getSeconds() < 60) {
log.trace("Directly scheduling the unmute, because it was below the threshold.");
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
scheduler.schedule(() -> {
unMuteScheduler.schedule(() -> {
try {
self.unmuteUser(mute);
self.endMute(mute.getId());
} catch (Exception exception) {
log.error("Failed to remind immediately.", exception);
}
@@ -217,18 +226,12 @@ public class MuteServiceBean implements MuteService {
@Override
@Transactional
public void unmuteUser(Mute mute) {
AServer mutingServer = mute.getMutingServer();
Optional<Mute> updatedMuteOpt = muteManagementService.findMute(mute.getId());
Mute updatedMute = updatedMuteOpt.orElseThrow(() -> new AbstractoRunTimeException(String.format("Cannot find mute with id %s", mute.getId())));
// we do not store any reference to the instant unmutes (<=60sec), so we cannot cancel it
// but if the person gets unmuted immediately, via command, this might still execute of the instant unmute
// so we need to load the mute, and check if the mute was unmuted already, because the mute object we have at
// hand was loaded earlier, and does not reflect the true state
if(Boolean.TRUE.equals(updatedMute.getMuteEnded())) {
log.info("Mute {} has ended already, {} does not need to be unmuted anymore.", mute.getId(), mute.getMutedUser().getUserReference().getId());
if(Boolean.TRUE.equals(mute.getMuteEnded())) {
log.info("Mute {} has ended already, user {} does not need to be unmuted anymore.", mute.getId(), mute.getMutedUser().getUserReference().getId());
return;
}
log.info("Unmuting {} in server {}", mutingServer.getId(), mute.getMutedUser().getUserReference().getId());
AServer mutingServer = mute.getMutingServer();
log.info("Unmuting {} in server {}", mute.getMutedUser().getUserReference().getId(), mutingServer.getId());
MuteRole muteRole = muteRoleManagementService.retrieveMuteRoleForServer(mutingServer);
log.trace("Using the mute role {} mapping to role {}", muteRole.getId(), muteRole.getRole().getId());
Guild guild = botService.getGuildByIdNullable(mute.getMutingServer().getId());
@@ -259,7 +262,7 @@ public class MuteServiceBean implements MuteService {
}
@Override
public void completelyUnmuteUser(AUserInAServer aUserInAServer) {
public void completelyUnMuteUser(AUserInAServer aUserInAServer) {
List<Mute> allMutesOfUser = muteManagementService.getAllMutesOf(aUserInAServer);
allMutesOfUser.forEach(mute -> {
mute.setMuteEnded(true);
@@ -269,7 +272,7 @@ public class MuteServiceBean implements MuteService {
}
@Override
public void completelyUnmuteUser(Member member) {
completelyUnmuteUser(userInServerManagementService.loadUser(member));
public void completelyUnMuteMember(Member member) {
completelyUnMuteUser(userInServerManagementService.loadUser(member));
}
}

View File

@@ -12,7 +12,6 @@ import net.dv8tion.jda.api.entities.MessageHistory;
import net.dv8tion.jda.api.entities.TextChannel;
import net.dv8tion.jda.api.utils.MiscUtil;
import net.dv8tion.jda.api.utils.TimeUtil;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@@ -37,9 +36,8 @@ public class PurgeServiceBean implements PurgeService {
return purgeMessages(amountToDelete, channel, startId, purgedMember, amountToDelete, 0, 0L);
}
@NotNull
private CompletableFuture<Void> purgeMessages(Integer amountToDelete, TextChannel channel, Long startId, Member purgedMember, Integer totalCount, Integer currentCount, Long statusMessageId) {
CompletableFuture<Void> deletionFuture = new CompletableFuture<>();
int toDeleteInThisIteration;
int messageLimit = 100;
if(amountToDelete >= messageLimit){
@@ -51,8 +49,9 @@ public class PurgeServiceBean implements PurgeService {
CompletableFuture<MessageHistory> historyFuture = channel.getHistoryBefore(startId, toDeleteInThisIteration).submit();
CompletableFuture<Long> statusMessageFuture = getOrCreatedStatusMessage(channel, totalCount, statusMessageId);
CompletableFuture<Void> coreFuture = CompletableFuture.allOf(historyFuture, statusMessageFuture);
coreFuture.thenAccept(voidParam -> {
CompletableFuture<Void> deletionFuture = new CompletableFuture<>();
CompletableFuture<Void> retrievalFuture = CompletableFuture.allOf(historyFuture, statusMessageFuture);
retrievalFuture.thenAccept(voidParam -> {
try {
List<Message> retrievedHistory = historyFuture.get().getRetrievedHistory();
List<Message> messagesToDeleteNow = filterMessagesToDelete(retrievedHistory, purgedMember);
@@ -70,7 +69,7 @@ public class PurgeServiceBean implements PurgeService {
if (messagesToDeleteNow.size() > 1) {
bulkDeleteMessages(channel, deletionFuture, messagesToDeleteNow, consumer);
} else if (messagesToDeleteNow.size() == 1) {
messagesToDeleteNow.get(0).delete().queue(consumer, deletionFuture::completeExceptionally);
latestMessage.delete().queue(consumer, deletionFuture::completeExceptionally);
}
} catch (Exception e) {
@@ -82,7 +81,7 @@ public class PurgeServiceBean implements PurgeService {
return null;
});
return CompletableFuture.allOf(coreFuture, deletionFuture);
return CompletableFuture.allOf(retrievalFuture, deletionFuture);
}
private void bulkDeleteMessages(TextChannel channel, CompletableFuture<Void> deletionFuture, List<Message> messagesToDeleteNow, Consumer<Void> consumer) {
@@ -127,8 +126,13 @@ public class PurgeServiceBean implements PurgeService {
private Consumer<Void> deletionConsumer(Integer amountToDelete, TextChannel channel, Member purgedMember, Integer totalCount, Integer currentCount, CompletableFuture<Void> deletionFuture, Long currentStatusMessageId, Message earliestMessage) {
return aVoid -> {
if (amountToDelete > 1) {
purgeMessages(amountToDelete, channel, earliestMessage.getIdLong(), purgedMember, totalCount, currentCount, currentStatusMessageId).thenAccept(aVoid1 ->
deletionFuture.complete(null)
purgeMessages(amountToDelete, channel, earliestMessage.getIdLong(), purgedMember, totalCount, currentCount, currentStatusMessageId).whenComplete((avoid, throwable) -> {
if (throwable != null) {
deletionFuture.completeExceptionally(throwable);
} else {
deletionFuture.complete(null);
}
}
);
} else {
channel.deleteMessageById(currentStatusMessageId).queueAfter(5, TimeUnit.SECONDS);

View File

@@ -29,7 +29,7 @@ public class SlowModeServiceBean implements SlowModeService {
}
@Override
public void disableSlowMOde(TextChannel channel) {
public void disableSlowMode(TextChannel channel) {
setSlowMode(channel, Duration.ZERO);
}

View File

@@ -1,10 +1,10 @@
package dev.sheldan.abstracto.moderation.service;
import dev.sheldan.abstracto.core.models.FullUser;
import dev.sheldan.abstracto.core.models.context.ServerContext;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.core.service.ConfigService;
import dev.sheldan.abstracto.core.service.MessageService;
import dev.sheldan.abstracto.moderation.config.features.WarningDecayFeature;
import dev.sheldan.abstracto.moderation.config.posttargets.WarnDecayPostTarget;
import dev.sheldan.abstracto.moderation.config.posttargets.WarningPostTarget;
import dev.sheldan.abstracto.moderation.models.template.job.WarnDecayLogModel;
@@ -55,11 +55,11 @@ public class WarnServiceBean implements WarnService {
@Autowired
private ConfigService configService;
private static final String WARN_LOG_TEMPLATE = "warn_log";
private static final String WARN_NOTIFICATION_TEMPLATE = "warn_notification";
public static final String WARN_LOG_TEMPLATE = "warn_log";
public static final String WARN_NOTIFICATION_TEMPLATE = "warn_notification";
@Override
public Warning warnUser(AUserInAServer warnedAUserInAServer, AUserInAServer warningAUserInAServer, String reason, TextChannel feedbackChannel) {
public Warning warnUser(AUserInAServer warnedAUserInAServer, AUserInAServer warningAUserInAServer, String reason, MessageChannel feedbackChannel) {
FullUser warnedUser = FullUser
.builder()
.aUserInAServer(warnedAUserInAServer)
@@ -71,11 +71,11 @@ public class WarnServiceBean implements WarnService {
.aUserInAServer(warningAUserInAServer)
.member(botService.getMemberInServer(warningAUserInAServer))
.build();
return warnUser(warnedUser, warningUser, reason, feedbackChannel);
return warnFullUser(warnedUser, warningUser, reason, feedbackChannel);
}
@Override
public Warning warnUser(Member warnedMember, Member warningMember, String reason, TextChannel feedbackChannel) {
public Warning warnMember(Member warnedMember, Member warningMember, String reason, MessageChannel feedbackChannel) {
FullUser warnedUser = FullUser
.builder()
.aUserInAServer(userInServerManagementService.loadUser(warnedMember))
@@ -87,13 +87,13 @@ public class WarnServiceBean implements WarnService {
.aUserInAServer(userInServerManagementService.loadUser(warningMember))
.member(warningMember)
.build();
return warnUser(warnedUser, warningUser, reason, feedbackChannel);
return warnFullUser(warnedUser, warningUser, reason, feedbackChannel);
}
@Override
public Warning warnUser(FullUser warnedMember, FullUser warningMember, String reason, TextChannel feedbackChannel) {
public Warning warnFullUser(FullUser warnedMember, FullUser warningMember, String reason, MessageChannel feedbackChannel) {
Guild guild = warnedMember.getMember().getGuild();
log.info("User {} is warning {} in server {} because of {}", warnedMember.getMember().getId(), warningMember.getMember().getId(), guild.getIdLong(), reason);
log.info("User {} is warning {} in server {}", warnedMember.getMember().getId(), warningMember.getMember().getId(), guild.getIdLong());
Warning warning = warnManagementService.createWarning(warnedMember.getAUserInAServer(), warningMember.getAUserInAServer(), reason);
WarnNotification warnNotification = WarnNotification.builder().warning(warning).serverName(guild.getName()).build();
String warnNotificationMessage = templateService.renderTemplate(WARN_NOTIFICATION_TEMPLATE, warnNotification);
@@ -102,16 +102,17 @@ public class WarnServiceBean implements WarnService {
}
@Override
public void warnUserWithLog(Member warnedMember, Member warningMember, String reason, WarnLog warnLog, TextChannel feedbackChannel) {
Warning warning = warnUser(warnedMember, warningMember, reason, feedbackChannel);
public Warning warnUserWithLog(Member warnedMember, Member warningMember, String reason, WarnLog warnLog, MessageChannel feedbackChannel) {
Warning warning = warnMember(warnedMember, warningMember, reason, feedbackChannel);
warnLog.setWarning(warning);
this.sendWarnLog(warnLog);
return warning;
}
@Override
@Transactional
public void decayWarningsForServer(AServer server) {
Long days = configService.getLongValue("decayDays", server.getId());
Long days = configService.getLongValue(WarningDecayFeature.DECAY_DAYS_KEY, server.getId());
Instant cutOffDay = Instant.now().minus(days, ChronoUnit.DAYS);
List<Warning> warningsToDecay = warnManagementService.getActiveWarningsInServerOlderThan(server, cutOffDay);
decayWarnings(warningsToDecay);
@@ -120,10 +121,13 @@ public class WarnServiceBean implements WarnService {
private void decayWarnings(List<Warning> warningsToDecay) {
Instant now = Instant.now();
warningsToDecay.forEach(warning -> {
warning.setDecayDate(now);
warning.setDecayed(true);
});
warningsToDecay.forEach(warning -> decayWarning(warning, now));
}
@Override
public void decayWarning(Warning warning, Instant now) {
warning.setDecayDate(now);
warning.setDecayed(true);
}
private void logDecayedWarnings(AServer server, List<Warning> warningsToDecay) {
@@ -156,7 +160,7 @@ public class WarnServiceBean implements WarnService {
}
}
private void sendWarnLog(ServerContext warnLogModel) {
private void sendWarnLog(WarnLog warnLogModel) {
MessageToSend message = templateService.renderEmbedTemplate(WARN_LOG_TEMPLATE, warnLogModel);
postTargetService.sendEmbedInPostTarget(message, WarningPostTarget.WARN_LOG, warnLogModel.getServer().getId());
}

View File

@@ -26,11 +26,10 @@ public class MuteManagementServiceBean implements MuteManagementService {
@Override
public Mute createMute(AUserInAServer mutedUser, AUserInAServer mutingUser, String reason, Instant unmuteDate, AServerAChannelMessage muteMessage) {
log.trace("Creating mute for user {} executed by user {} in server {}, user will be unmuted at {}",
log.trace("Creating mute for user {} executed by user {} in server {}, user will be un-muted at {}",
mutedUser.getUserReference().getId(), mutingUser.getUserReference().getId(), mutedUser.getServerReference().getId(), unmuteDate);
Mute mute = Mute
.builder()
.muteDate(Instant.now())
.mutedUser(mutedUser)
.mutingUser(mutingUser)
.muteTargetDate(unmuteDate)
@@ -60,6 +59,11 @@ public class MuteManagementServiceBean implements MuteManagementService {
return muteRepository.existsByMutedUserAndMuteEndedFalse(userInAServer);
}
@Override
public boolean hasActiveMute(Member member) {
return muteRepository.existsByMutedUserAndMuteEndedFalse(userInServerManagementService.loadUser(member));
}
@Override
public Mute getAMuteOf(AUserInAServer userInAServer) {
return muteRepository.findTopByMutedUserAndMuteEndedFalse(userInAServer);

View File

@@ -42,10 +42,10 @@ public class MuteRoleManagementServiceBean implements MuteRoleManagementService
@Override
public MuteRole setMuteRoleForServer(AServer server, ARole role) {
log.info("Setting muted role for server {} to role {}", server.getId(), role.getId());
MuteRole existing = retrieveMuteRoleForServer(server);
if(existing == null) {
if(!muteRoleForServerExists(server)) {
return createMuteRoleForServer(server, role);
} else {
MuteRole existing = retrieveMuteRoleForServer(server);
log.trace("Updating mute role for server {} to be role {} instead.", server.getId(), role.getId());
existing.setRole(role);
return existing;
@@ -54,6 +54,6 @@ public class MuteRoleManagementServiceBean implements MuteRoleManagementService
@Override
public boolean muteRoleForServerExists(AServer server) {
return retrieveMuteRoleForServer(server) != null;
return muteRoleRepository.existsByRoleServer(server);
}
}

View File

@@ -15,7 +15,6 @@ public class UserNoteManagementServiceBean implements UserNoteManagementService
@Autowired
private UserNoteRepository userNoteRepository;
@Override
public UserNote createUserNote(AUserInAServer aUserInAServer, String note) {
UserNote newNote = UserNote

View File

@@ -0,0 +1,32 @@
{
"author": {
"name": "${bannedUser.effectiveName}",
"avatar": "${bannedUser.user.effectiveAvatarUrl}"
},
"title": {
"title": "<#include "ban_log_title">"
},
"color" : {
"r": 200,
"g": 0,
"b": 255
},
"fields": [
{
"name": "<#include "ban_log_banned_user_field_title">",
"value": "${bannedUser.effectiveName} ${bannedUser.asMention} (${bannedUser.idLong?c})"
},
{
"name": "<#include "ban_log_banning_user_field_title">",
"value": "${banningUser.effectiveName} ${banningUser.asMention} (${banningUser.idLong?c})"
},
{
"name": "<#include "ban_log_jump_link_field_title">",
"value": "[${messageChannel.name}](${message.jumpUrl})"
},
{
"name": "<#include "ban_log_reason_field_title">",
"value": "${reason}"
}
]
}

View File

@@ -0,0 +1,28 @@
{
"title": {
"title": "<#include "ban_log_title">"
},
"color" : {
"r": 200,
"g": 0,
"b": 255
},
"fields": [
{
"name": "<#include "ban_log_banned_user_field_title">",
"value": "${bannedUserId?c}"
},
{
"name": "<#include "ban_log_banning_user_field_title">",
"value": "${banningUser.effectiveName} ${banningUser.asMention} (${banningUser.idLong?c})"
},
{
"name": "<#include "ban_log_jump_link_field_title">",
"value": "[${messageChannel.name}](${message.jumpUrl})"
},
{
"name": "<#include "ban_log_reason_field_title">",
"value": "${reason}"
}
]
}

View File

@@ -0,0 +1,32 @@
{
"author": {
"name": "${kickedUser.effectiveName}",
"avatar": "${kickedUser.user.effectiveAvatarUrl}"
},
"title": {
"title": "<#include "kick_log_title">"
},
"color" : {
"r": 200,
"g": 0,
"b": 255
},
"fields": [
{
"name": "<#include "kick_log_kicked_user_field_title">",
"value": "${kickedUser.effectiveName} ${kickedUser.asMention} (${kickedUser.idLong?c})"
},
{
"name": "<#include "kick_log_kicking_user_field_title">",
"value": "${kickingUser.effectiveName} ${kickingUser.asMention} (${kickingUser.idLong?c})"
},
{
"name": "<#include "kick_log_jump_link_field_title">",
"value": "[${messageChannel.name}](${message.jumpUrl})"
},
{
"name": "<#include "kick_log_reason_field_title">",
"value": "${reason}"
}
]
}

View File

@@ -12,11 +12,11 @@
"fields": [
{
"name": "<#include "messageDeleted_original_message_field_title">",
"value": "${message.content}"
"value": "${cachedMessage.content}"
},
{
"name": "<#include "messageDeleted_message_link_field_title">",
"value": "[${messageChannel.name}](${message.messageUrl})"
"value": "[${messageChannel.name}](${cachedMessage.messageUrl})"
}
]
}