added ability to configure paginators to be used

added paginator for warnings command
This commit is contained in:
Sheldan
2020-05-09 21:31:31 +02:00
parent 1e203c19e0
commit 860aa0eed7
17 changed files with 306 additions and 6 deletions

View File

@@ -0,0 +1,92 @@
package dev.sheldan.abstracto.moderation.commands;
import com.jagrosh.jdautilities.commons.waiter.EventWaiter;
import com.jagrosh.jdautilities.menu.ButtonMenu;
import com.jagrosh.jdautilities.menu.Paginator;
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.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;
import dev.sheldan.abstracto.moderation.config.features.ModerationFeatures;
import dev.sheldan.abstracto.moderation.converter.WarnEntryConverter;
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;
import javax.naming.Context;
import java.util.ArrayList;
import java.util.List;
@Component
public class Warnings extends AbstractConditionableCommand {
@Autowired
private BotService botService;
@Autowired
private WarnManagementService warnManagementService;
@Autowired
private TemplateService templateService;
@Autowired
private UserInServerManagementService userInServerManagementService;
@Autowired
private WarnEntryConverter warnEntryConverter;
@Autowired
private PaginatorService paginatorService;
@Override
public CommandResult execute(CommandContext commandContext) {
List<Warning> warnsToDisplay;
if(commandContext.getParameters().getParameters().size() > 0) {
Member member = (Member) commandContext.getParameters().getParameters().get(0);
warnsToDisplay = warnManagementService.getAllWarnsForUser(userInServerManagementService.loadUser(member));
} else {
warnsToDisplay = warnManagementService.getAllWarningsOfServer(commandContext.getUserInitiatedContext().getServer());
}
List<WarnEntry> warnEntries = warnEntryConverter.fromWarnings(warnsToDisplay);
WarningsModel model = (WarningsModel) ContextConverter.fromCommandContext(commandContext, WarningsModel.class);
model.setWarnings(warnEntries);
Paginator paginator = paginatorService.createPaginatorFromTemplate("warnings_response", model, new EventWaiter());
paginator.display(commandContext.getChannel());
return CommandResult.fromSuccess();
}
@Override
public CommandConfiguration getConfiguration() {
List<Parameter> parameters = new ArrayList<>();
parameters.add(Parameter.builder().name("user").type(Member.class).optional(true).build());
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();
return CommandConfiguration.builder()
.name("warnings")
.module(ModerationModule.MODERATION)
.templated(true)
.causesReaction(true)
.parameters(parameters)
.help(helpInfo)
.build();
}
@Override
public FeatureEnum getFeature() {
return ModerationFeatures.WARNING;
}
}

View File

@@ -0,0 +1,47 @@
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;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
@Component
public class WarnEntryConverter {
@Autowired
private UserInServerManagementService userInServerManagementService;
@Autowired
private BotService botService;
public List<WarnEntry> fromWarnings(List<Warning> warnings) {
List<WarnEntry> entries = new ArrayList<>();
warnings.forEach(warning -> {
FullUser warnedUser = FullUser
.builder()
.member(botService.getMemberInServer(warning.getWarnedUser()))
.aUserInAServer(warning.getWarnedUser())
.build();
FullUser warningUser = FullUser
.builder()
.member(botService.getMemberInServer(warning.getWarningUser()))
.aUserInAServer(warning.getWarningUser())
.build();
WarnEntry entry = WarnEntry
.builder()
.warnedUser(warnedUser)
.warningUser(warningUser)
.warning(warning)
.build();
entries.add(entry);
});
return entries;
}
}

View File

@@ -16,9 +16,16 @@ public interface WarnRepository extends JpaRepository<Warning, Long> {
@QueryHints(@QueryHint(name = org.hibernate.annotations.QueryHints.CACHEABLE, value = "true")) @QueryHints(@QueryHint(name = org.hibernate.annotations.QueryHints.CACHEABLE, value = "true"))
List<Warning> findAllByWarnedUser_ServerReferenceAndDecayedFalseAndWarnDateLessThan(AServer server, Instant cutOffDate); List<Warning> findAllByWarnedUser_ServerReferenceAndDecayedFalseAndWarnDateLessThan(AServer server, Instant cutOffDate);
@QueryHints(@QueryHint(name = org.hibernate.annotations.QueryHints.CACHEABLE, value = "true"))
List<Warning> findAllByWarnedUser_ServerReference(AServer server);
@QueryHints(@QueryHint(name = org.hibernate.annotations.QueryHints.CACHEABLE, value = "true")) @QueryHints(@QueryHint(name = org.hibernate.annotations.QueryHints.CACHEABLE, value = "true"))
Long countByWarnedUser(AUserInAServer aUserInAServer); Long countByWarnedUser(AUserInAServer aUserInAServer);
@QueryHints(@QueryHint(name = org.hibernate.annotations.QueryHints.CACHEABLE, value = "true")) @QueryHints(@QueryHint(name = org.hibernate.annotations.QueryHints.CACHEABLE, value = "true"))
Long countByWarnedUserAndDecayedFalse(AUserInAServer aUserInAServer); Long countByWarnedUserAndDecayedFalse(AUserInAServer aUserInAServer);
@QueryHints(@QueryHint(name = org.hibernate.annotations.QueryHints.CACHEABLE, value = "true"))
List<Warning> findByWarnedUser(AUserInAServer aUserInAServer);
} }

View File

@@ -39,6 +39,16 @@ public class WarnManagementServiceBean implements WarnManagementService {
return warnRepository.countByWarnedUser(aUserInAServer); return warnRepository.countByWarnedUser(aUserInAServer);
} }
@Override
public List<Warning> getAllWarnsForUser(AUserInAServer aUserInAServer) {
return warnRepository.findByWarnedUser(aUserInAServer);
}
@Override
public List<Warning> getAllWarningsOfServer(AServer server) {
return warnRepository.findAllByWarnedUser_ServerReference(server);
}
@Override @Override
public Long getActiveWarnsForUser(AUserInAServer aUserInAServer) { public Long getActiveWarnsForUser(AUserInAServer aUserInAServer) {
return warnRepository.countByWarnedUserAndDecayedFalse(aUserInAServer); return warnRepository.countByWarnedUserAndDecayedFalse(aUserInAServer);

View File

@@ -0,0 +1,7 @@
{
<#assign warnCount>${warnings?size}</#assign>
"headerText": "<#include "warnings_header_text">",
"items": [
<#list warnings as warning>"<#include "warnings_warn_entry">"<#sep>,</#list>
]
}

View File

@@ -0,0 +1,11 @@
<#assign warnId>${warning.warning.id}</#assign>
<#assign reason>${warning.warning.reason}</#assign>
<#assign warnedUserText><#if warning.warnedUser.member??>${warning.warnedUser.member.asMention}(${warning.warnedUser.member.user.id})<#else>${warning.warnedUser.aUserInAServer.id}</#if></#assign>
<#assign warningUserText><#if warning.warningUser.member??>${warning.warningUser.member.asMention}(${warning.warningUser.member.user.id})<#else>${warning.warningUser.aUserInAServer.id}</#if></#assign>
<#assign warnDate>${formatInstant(warning.warning.warnDate, "yyyy-MM-dd HH:mm:ss")}</#assign>
<#include "warnings_warn_entry_text">
<#if warning.warning.decayed>
<#assign decayDate>${formatInstant(warning.warning.decayDate, "yyyy-MM-dd HH:mm:ss")}</#assign>
<#include "warnings_warn_is_decayed">
</#if>

View File

@@ -0,0 +1,16 @@
package dev.sheldan.abstracto.moderation.models.template.commands;
import dev.sheldan.abstracto.core.models.FullUser;
import dev.sheldan.abstracto.moderation.models.database.Warning;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
@Builder
public class WarnEntry {
private Warning warning;
private FullUser warnedUser;
private FullUser warningUser;
}

View File

@@ -0,0 +1,15 @@
package dev.sheldan.abstracto.moderation.models.template.commands;
import dev.sheldan.abstracto.core.models.context.UserInitiatedServerContext;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.SuperBuilder;
import java.util.List;
@Getter
@Setter
@SuperBuilder
public class WarningsModel extends UserInitiatedServerContext {
private List<WarnEntry> warnings;
}

View File

@@ -12,5 +12,7 @@ public interface WarnManagementService {
Warning createWarning(AUserInAServer warnedAUser, AUserInAServer warningAUser, String reason); Warning createWarning(AUserInAServer warnedAUser, AUserInAServer warningAUser, String reason);
List<Warning> getActiveWarningsInServerOlderThan(AServer server, Instant date); List<Warning> getActiveWarningsInServerOlderThan(AServer server, Instant date);
Long getTotalWarnsForUser(AUserInAServer aUserInAServer); Long getTotalWarnsForUser(AUserInAServer aUserInAServer);
List<Warning> getAllWarnsForUser(AUserInAServer aUserInAServer);
List<Warning> getAllWarningsOfServer(AServer server);
Long getActiveWarnsForUser(AUserInAServer aUserInAServer); Long getActiveWarnsForUser(AUserInAServer aUserInAServer);
} }

View File

@@ -0,0 +1,18 @@
package dev.sheldan.abstracto.core.model;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
import java.util.List;
@Getter
@Setter
@Builder
public class PaginatorConfiguration {
private String headerText;
private List<String> items;
private Long timeoutSeconds;
private Boolean showPageNumbers;
private Boolean useNumberedItems;
}

View File

@@ -0,0 +1,70 @@
package dev.sheldan.abstracto.core.service;
import com.google.gson.Gson;
import com.jagrosh.jdautilities.commons.waiter.EventWaiter;
import com.jagrosh.jdautilities.menu.Paginator;
import dev.sheldan.abstracto.core.model.PaginatorConfiguration;
import dev.sheldan.abstracto.templating.service.TemplateService;
import net.dv8tion.jda.api.entities.MessageEmbed;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.concurrent.TimeUnit;
@Component
public class PaginatorServiceBean implements PaginatorService {
@Autowired
private BotService botService;
@Autowired
private TemplateService templateService;
@Autowired
private Gson gson;
@Override
public Paginator createPaginatorFromTemplate(String templateKey, Object model, EventWaiter waiter) {
String embedConfig = templateService.renderTemplate(templateKey + "_paginator", model);
PaginatorConfiguration configuration = gson.fromJson(embedConfig, PaginatorConfiguration.class);
botService.getInstance().addEventListener(waiter);
List<String> items = configuration.getItems();
int itemsPerPage = findAppropriateCountPerPage(items);
return new Paginator.Builder()
.setItemsPerPage(itemsPerPage)
.setText(configuration.getHeaderText())
.showPageNumbers(ObjectUtils.defaultIfNull(configuration.getShowPageNumbers(), false))
.setItems(configuration.getItems().toArray(new String[0]))
.useNumberedItems(ObjectUtils.defaultIfNull(configuration.getUseNumberedItems(), false))
.setEventWaiter(waiter)
.setTimeout(ObjectUtils.defaultIfNull(configuration.getTimeoutSeconds(), 120L), TimeUnit.SECONDS)
.setFinalAction(message -> {
botService.getInstance().removeEventListener(waiter);
message.delete().queue();
})
.build();
}
private int findAppropriateCountPerPage(List<String> items) {
int currentMin = Integer.MAX_VALUE;
// to be sure, because the paginator adds some characters here and there
int carefulMax = MessageEmbed.TEXT_MAX_LENGTH - 50;
for (int i = 0; i < items.size(); i++) {
int count = 0;
int length = 0;
for (String innerItem : items) {
length += innerItem.length();
if (length > carefulMax) {
currentMin = Math.min(currentMin, count);
break;
}
count++;
}
}
return currentMin;
}
}

View File

@@ -0,0 +1,8 @@
package dev.sheldan.abstracto.core.service;
import com.jagrosh.jdautilities.commons.waiter.EventWaiter;
import com.jagrosh.jdautilities.menu.Paginator;
public interface PaginatorService {
Paginator createPaginatorFromTemplate(String templateKey, Object model, EventWaiter waiter);
}

View File

@@ -0,0 +1 @@
Warnings #${warnId} with reason: ${reason} towards user ${warnedUserText} by user ${warningUserText} on `${warnDate}`.

View File

@@ -29,10 +29,6 @@ public class TemplateServiceBean implements TemplateService {
@Autowired @Autowired
private Gson gson; private Gson gson;
@Override
public String renderTemplate(Template template) {
return null;
}
private String getPageString(Integer count) { private String getPageString(Integer count) {
HashMap<String, Object> params = new HashMap<>(); HashMap<String, Object> params = new HashMap<>();

View File

@@ -1,12 +1,10 @@
package dev.sheldan.abstracto.templating.service; package dev.sheldan.abstracto.templating.service;
import dev.sheldan.abstracto.templating.model.MessageToSend; import dev.sheldan.abstracto.templating.model.MessageToSend;
import dev.sheldan.abstracto.templating.model.database.Template;
import java.util.HashMap; import java.util.HashMap;
public interface TemplateService { public interface TemplateService {
String renderTemplate(Template template);
MessageToSend renderEmbedTemplate(String key, Object model); MessageToSend renderEmbedTemplate(String key, Object model);
String renderTemplateWithMap(String key, HashMap<String, Object> parameters); String renderTemplateWithMap(String key, HashMap<String, Object> parameters);
String renderTemplate(String key, Object model); String renderTemplate(String key, Object model);