mirror of
https://github.com/Sheldan/abstracto.git
synced 2026-01-25 03:04:50 +00:00
added unmute command to end all mutes, and remove the current one, this also cancels all running jobs, so we need to store the triggers
enabled voice state cache, as its necessary for voice state operations kick user out of voice chat, if they are in any changed unmute date to the the effective date of the unmute, instead of the planned date added possibility to stop a job via the trigger key
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
package dev.sheldan.abstracto.moderation.commands;
|
||||
package dev.sheldan.abstracto.moderation.commands.mute;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
|
||||
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
|
||||
@@ -1,4 +1,4 @@
|
||||
package dev.sheldan.abstracto.moderation.commands;
|
||||
package dev.sheldan.abstracto.moderation.commands.mute;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
|
||||
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
|
||||
@@ -0,0 +1,64 @@
|
||||
package dev.sheldan.abstracto.moderation.commands.mute;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
|
||||
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
|
||||
import dev.sheldan.abstracto.core.command.config.HelpInfo;
|
||||
import dev.sheldan.abstracto.core.command.config.Parameter;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandContext;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.moderation.Moderation;
|
||||
import dev.sheldan.abstracto.moderation.config.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 net.dv8tion.jda.api.entities.Member;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
public class UnMute extends AbstractConditionableCommand {
|
||||
|
||||
@Autowired
|
||||
private MuteService muteService;
|
||||
|
||||
@Autowired
|
||||
private MuteManagementService muteManagementService;
|
||||
|
||||
@Override
|
||||
public CommandResult execute(CommandContext 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");
|
||||
}
|
||||
muteService.unmuteUser(mute);
|
||||
muteService.cancelUnmuteJob(mute);
|
||||
muteService.completelyUnmuteUser(member);
|
||||
return CommandResult.fromSuccess();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandConfiguration getConfiguration() {
|
||||
List<Parameter> parameters = new ArrayList<>();
|
||||
parameters.add(Parameter.builder().name("user").type(Member.class).build());
|
||||
HelpInfo helpInfo = HelpInfo.builder().templated(false).build();
|
||||
return CommandConfiguration.builder()
|
||||
.name("unMute")
|
||||
.module(Moderation.MODERATION)
|
||||
.templated(false)
|
||||
.causesReaction(true)
|
||||
.parameters(parameters)
|
||||
.help(helpInfo)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFeature() {
|
||||
return ModerationFeatures.MUTING;
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,11 @@ import dev.sheldan.abstracto.moderation.models.database.Mute;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Repository
|
||||
public interface MuteRepository extends JpaRepository<Mute, Long> {
|
||||
boolean existsByMutedUserAndMuteEndedFalse(AUserInAServer userInAServer);
|
||||
Mute findTopByMutedUserAndMuteEndedFalse(AUserInAServer userInAServer);
|
||||
List<Mute> findAllByMutedUserAndMuteEndedFalseOrderByIdDesc(AUserInAServer aUserInAServer);
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
@@ -112,8 +113,9 @@ public class MuteServiceBean implements MuteService {
|
||||
|
||||
@Override
|
||||
public Mute muteUser(FullUser userBeingMuted, FullUser userMuting, String reason, Instant unmuteDate, Message message) {
|
||||
Member memberBeingMuted = userBeingMuted.getMember();
|
||||
log.info("User {} mutes {} until {}",
|
||||
userBeingMuted.getMember().getIdLong(), userMuting.getMember().getIdLong(), unmuteDate);
|
||||
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 {
|
||||
@@ -136,14 +138,19 @@ public class MuteServiceBean implements MuteService {
|
||||
.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(userBeingMuted.getMember().getGuild().getName()).build();
|
||||
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(userBeingMuted.getMember().getUser(), muteNotificationMessage, textChannel);
|
||||
messageService.sendMessageToUser(memberBeingMuted.getUser(), muteNotificationMessage, textChannel);
|
||||
|
||||
startUnmuteJobFor(unmuteDate, mute);
|
||||
String triggerKey = startUnmuteJobFor(unmuteDate, mute);
|
||||
mute.setTriggerKey(triggerKey);
|
||||
muteManagementService.saveMute(mute);
|
||||
return mute;
|
||||
}
|
||||
|
||||
@@ -154,7 +161,7 @@ public class MuteServiceBean implements MuteService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startUnmuteJobFor(Instant unmuteDate, Mute mute) {
|
||||
public String startUnmuteJobFor(Instant unmuteDate, Mute mute) {
|
||||
Duration muteDuration = Duration.between(Instant.now(), unmuteDate);
|
||||
if(muteDuration.getSeconds() < 60) {
|
||||
log.trace("Directly scheduling the unmute, because it was below the threshold.");
|
||||
@@ -166,11 +173,19 @@ public class MuteServiceBean implements MuteService {
|
||||
log.error("Failed to remind immediately.", exception);
|
||||
}
|
||||
}, muteDuration.toNanos(), TimeUnit.NANOSECONDS);
|
||||
return null;
|
||||
} else {
|
||||
log.trace("Starting scheduled job to execute unmute.");
|
||||
JobDataMap parameters = new JobDataMap();
|
||||
parameters.putAsString("muteId", mute.getId());
|
||||
schedulerService.executeJobWithParametersOnce("unMuteJob", "moderation", parameters, Date.from(unmuteDate));
|
||||
return schedulerService.executeJobWithParametersOnce("unMuteJob", "moderation", parameters, Date.from(unmuteDate));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancelUnmuteJob(Mute mute) {
|
||||
if(mute.getTriggerKey() != null) {
|
||||
schedulerService.stopTrigger(mute.getTriggerKey());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -198,6 +213,15 @@ public class MuteServiceBean implements MuteService {
|
||||
@Transactional
|
||||
public void unmuteUser(Mute mute) {
|
||||
AServer mutingServer = mute.getMutingServer();
|
||||
Mute updatedMute = muteManagementService.findMute(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(updatedMute.getMuteEnded()) {
|
||||
log.info("Mute {} has ended already, {} 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());
|
||||
MuteRole muteRole = muteRoleManagementService.retrieveMuteRoleForServer(mutingServer);
|
||||
log.trace("Using the mute role {} mapping to role {}", muteRole.getId(), muteRole.getRole().getId());
|
||||
@@ -227,4 +251,19 @@ public class MuteServiceBean implements MuteService {
|
||||
Mute mute = muteManagementService.findMute(muteId);
|
||||
unmuteUser(mute);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void completelyUnmuteUser(AUserInAServer aUserInAServer) {
|
||||
List<Mute> allMutesOfUser = muteManagementService.getAllMutesOf(aUserInAServer);
|
||||
allMutesOfUser.forEach(mute -> {
|
||||
mute.setMuteEnded(true);
|
||||
cancelUnmuteJob(mute);
|
||||
muteManagementService.saveMute(mute);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void completelyUnmuteUser(Member member) {
|
||||
completelyUnmuteUser(userManagementService.loadUser(member));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,13 +2,16 @@ package dev.sheldan.abstracto.moderation.service.management;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.AServerAChannelMessage;
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.core.service.management.UserManagementService;
|
||||
import dev.sheldan.abstracto.moderation.models.database.Mute;
|
||||
import dev.sheldan.abstracto.moderation.repository.MuteRepository;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
@@ -17,6 +20,9 @@ public class MuteManagementServiceBean implements MuteManagementService {
|
||||
@Autowired
|
||||
private MuteRepository muteRepository;
|
||||
|
||||
@Autowired
|
||||
private UserManagementService userManagementService;
|
||||
|
||||
@Override
|
||||
public Mute createMute(AUserInAServer aUserInAServer, AUserInAServer mutingUser, String reason, Instant unmuteDate, AServerAChannelMessage origin) {
|
||||
log.trace("Creating mute for user {} executed by user {} in server {}, user will be unmuted at {}",
|
||||
@@ -53,5 +59,20 @@ public class MuteManagementServiceBean implements MuteManagementService {
|
||||
return muteRepository.existsByMutedUserAndMuteEndedFalse(userInAServer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mute getAMuteOf(AUserInAServer userInAServer) {
|
||||
return muteRepository.findTopByMutedUserAndMuteEndedFalse(userInAServer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mute getAMuteOf(Member userInAServer) {
|
||||
return getAMuteOf(userManagementService.loadUser(userInAServer));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Mute> getAllMutesOf(AUserInAServer aUserInAServer) {
|
||||
return muteRepository.findAllByMutedUserAndMuteEndedFalseOrderByIdDesc(aUserInAServer);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -51,5 +51,5 @@
|
||||
"footer": {
|
||||
"text": "Mute #${mute.id}"
|
||||
},
|
||||
"timeStamp": "${mute.muteTargetDate}"
|
||||
"timeStamp": "${unmuteDate}"
|
||||
}
|
||||
@@ -48,5 +48,7 @@ public class Mute {
|
||||
@JoinColumn(name = "mutingChannel")
|
||||
private AChannel mutingChannel;
|
||||
|
||||
private String triggerKey;
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ import lombok.experimental.SuperBuilder;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
|
||||
|
||||
@Getter
|
||||
@@ -22,9 +23,17 @@ public class UnMuteLog extends ServerContext {
|
||||
private Mute mute;
|
||||
|
||||
public Duration getMuteDuration() {
|
||||
return Duration.between(mute.getMuteDate(), Instant.now());
|
||||
}
|
||||
|
||||
public Duration getPlannedMuteDuration() {
|
||||
return Duration.between(mute.getMuteDate(), mute.getMuteTargetDate());
|
||||
}
|
||||
|
||||
public Instant getUnmuteDate() {
|
||||
return Instant.now();
|
||||
}
|
||||
|
||||
public String getMessageUrl() {
|
||||
return MessageUtils.buildMessageUrl(this.mute.getMutingServer().getId() ,this.getMute().getMutingChannel().getId(), this.mute.getMessageId());
|
||||
}
|
||||
|
||||
@@ -15,7 +15,10 @@ public interface MuteService {
|
||||
Mute muteUser(FullUser userToMute, FullUser userMuting, String reason, Instant unmuteDate, Message message);
|
||||
void applyMuteRole(AUserInAServer aUserInAServer);
|
||||
void muteMemberWithLog(Member memberToMute, Member memberMuting, String reason, Instant unmuteDate, MuteLog log, Message message);
|
||||
void startUnmuteJobFor(Instant unmuteDate, Mute mute);
|
||||
String startUnmuteJobFor(Instant unmuteDate, Mute mute);
|
||||
void cancelUnmuteJob(Mute mute);
|
||||
void unmuteUser(Mute mute);
|
||||
void endMute(Long muteId);
|
||||
void completelyUnmuteUser(AUserInAServer aUserInAServer);
|
||||
void completelyUnmuteUser(Member member);
|
||||
}
|
||||
|
||||
@@ -3,12 +3,17 @@ package dev.sheldan.abstracto.moderation.service.management;
|
||||
import dev.sheldan.abstracto.core.models.AServerAChannelMessage;
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.moderation.models.database.Mute;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.List;
|
||||
|
||||
public interface MuteManagementService {
|
||||
Mute createMute(AUserInAServer aUserInAServer, AUserInAServer mutingUser, String reason, Instant unmuteDate, AServerAChannelMessage creation);
|
||||
Mute findMute(Long muteId);
|
||||
Mute saveMute(Mute mute);
|
||||
boolean hasActiveMute(AUserInAServer userInAServer);
|
||||
Mute getAMuteOf(AUserInAServer userInAServer);
|
||||
Mute getAMuteOf(Member userInAServer);
|
||||
List<Mute> getAllMutesOf(AUserInAServer aUserInAServer);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user