mirror of
https://github.com/Sheldan/Sissi.git
synced 2026-01-07 01:38:27 +00:00
[SIS-15] adding optional donation listing to donation command
refactoring to use the proper API instead of relying on parsing prepare for release
This commit is contained in:
@@ -10,6 +10,13 @@
|
|||||||
<groupId>dev.sheldan.sissi.application.module</groupId>
|
<groupId>dev.sheldan.sissi.application.module</groupId>
|
||||||
<artifactId>debra</artifactId>
|
<artifactId>debra</artifactId>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.google.code.gson</groupId>
|
||||||
|
<artifactId>gson</artifactId>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
<plugins>
|
<plugins>
|
||||||
<plugin>
|
<plugin>
|
||||||
|
|||||||
@@ -4,24 +4,32 @@ import dev.sheldan.abstracto.core.command.UtilityModuleDefinition;
|
|||||||
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
|
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
|
||||||
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
|
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
|
||||||
import dev.sheldan.abstracto.core.command.config.HelpInfo;
|
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.CommandContext;
|
||||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||||
|
import dev.sheldan.abstracto.core.exception.AbstractoRunTimeException;
|
||||||
import dev.sheldan.abstracto.core.interaction.InteractionService;
|
import dev.sheldan.abstracto.core.interaction.InteractionService;
|
||||||
import dev.sheldan.abstracto.core.interaction.slash.SlashCommandConfig;
|
import dev.sheldan.abstracto.core.interaction.slash.SlashCommandConfig;
|
||||||
|
import dev.sheldan.abstracto.core.interaction.slash.parameter.SlashCommandParameterService;
|
||||||
import dev.sheldan.abstracto.core.service.ChannelService;
|
import dev.sheldan.abstracto.core.service.ChannelService;
|
||||||
import dev.sheldan.abstracto.core.templating.model.MessageToSend;
|
import dev.sheldan.abstracto.core.templating.model.MessageToSend;
|
||||||
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
||||||
import dev.sheldan.abstracto.core.utils.FutureUtils;
|
import dev.sheldan.abstracto.core.utils.FutureUtils;
|
||||||
import dev.sheldan.sissi.module.debra.config.DebraFeatureDefinition;
|
import dev.sheldan.sissi.module.debra.config.DebraFeatureDefinition;
|
||||||
import dev.sheldan.sissi.module.debra.config.DebraSlashCommandNames;
|
import dev.sheldan.sissi.module.debra.config.DebraSlashCommandNames;
|
||||||
|
import dev.sheldan.sissi.module.debra.converter.DonationConverter;
|
||||||
|
import dev.sheldan.sissi.module.debra.model.api.DonationsResponse;
|
||||||
import dev.sheldan.sissi.module.debra.model.commands.DonationsModel;
|
import dev.sheldan.sissi.module.debra.model.commands.DonationsModel;
|
||||||
import dev.sheldan.sissi.module.debra.service.DonationService;
|
import dev.sheldan.sissi.module.debra.service.DonationService;
|
||||||
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
|
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
|
|
||||||
@@ -30,6 +38,8 @@ public class Donations extends AbstractConditionableCommand {
|
|||||||
|
|
||||||
private static final String DONATIONS_COMMAND_NAME = "donations";
|
private static final String DONATIONS_COMMAND_NAME = "donations";
|
||||||
private static final String DONATIONS_RESPONSE_TEMPLATE_KEY = "donations_response";
|
private static final String DONATIONS_RESPONSE_TEMPLATE_KEY = "donations_response";
|
||||||
|
private static final String SELECTION_PARAMETER = "type";
|
||||||
|
private static final String SELECTION_VALUE_PARAMETER = "parametervalue";
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private ChannelService channelService;
|
private ChannelService channelService;
|
||||||
@@ -43,26 +53,81 @@ public class Donations extends AbstractConditionableCommand {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private TemplateService templateService;
|
private TemplateService templateService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private DonationConverter donationConverter;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private SlashCommandParameterService slashCommandParameterService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompletableFuture<CommandResult> executeAsync(CommandContext commandContext) {
|
public CompletableFuture<CommandResult> executeAsync(CommandContext commandContext) {
|
||||||
MessageToSend messageToSend = getDonationMessageToSend();
|
List<Object> parameters = commandContext.getParameters().getParameters();
|
||||||
|
MessageToSend messageToSend;
|
||||||
|
if(parameters.isEmpty()) {
|
||||||
|
messageToSend = getDonationMessageToSend(commandContext.getGuild().getIdLong(), null, null);
|
||||||
|
} else {
|
||||||
|
String type = (String) parameters.get(0);
|
||||||
|
Integer selectionValue = (Integer) parameters.get(1);
|
||||||
|
Integer top = null;
|
||||||
|
Integer latest = null;
|
||||||
|
switch (type) {
|
||||||
|
case "top": top = selectionValue; break;
|
||||||
|
default:
|
||||||
|
case "latest" :
|
||||||
|
latest = selectionValue; break;
|
||||||
|
}
|
||||||
|
messageToSend = getDonationMessageToSend(commandContext.getGuild().getIdLong(), top, latest);
|
||||||
|
}
|
||||||
return FutureUtils.toSingleFutureGeneric(channelService.sendMessageToSendToChannel(messageToSend, commandContext.getChannel()))
|
return FutureUtils.toSingleFutureGeneric(channelService.sendMessageToSendToChannel(messageToSend, commandContext.getChannel()))
|
||||||
.thenApply(unused -> CommandResult.fromSuccess());
|
.thenApply(unused -> CommandResult.fromSuccess());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompletableFuture<CommandResult> executeSlash(SlashCommandInteractionEvent event) {
|
public CompletableFuture<CommandResult> executeSlash(SlashCommandInteractionEvent event) {
|
||||||
MessageToSend messageToSend = getDonationMessageToSend();
|
String selectionType = null;
|
||||||
|
if(slashCommandParameterService.hasCommandOption(SELECTION_PARAMETER, event)) {
|
||||||
|
selectionType = slashCommandParameterService.getCommandOption(SELECTION_PARAMETER, event, String.class);
|
||||||
|
}
|
||||||
|
Integer selectionValue = 5;
|
||||||
|
if(slashCommandParameterService.hasCommandOption(SELECTION_VALUE_PARAMETER, event)) {
|
||||||
|
selectionValue = slashCommandParameterService.getCommandOption(SELECTION_VALUE_PARAMETER, event, Integer.class);
|
||||||
|
}
|
||||||
|
if(selectionValue > 20) {
|
||||||
|
selectionValue = 5;
|
||||||
|
}
|
||||||
|
Integer top = null;
|
||||||
|
Integer latest = null;
|
||||||
|
if(selectionType != null) {
|
||||||
|
switch (selectionType) {
|
||||||
|
case "top": top = selectionValue; break;
|
||||||
|
default:
|
||||||
|
case "latest" :
|
||||||
|
latest = selectionValue; break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MessageToSend messageToSend = getDonationMessageToSend(event.getGuild().getIdLong(), top, latest);
|
||||||
return interactionService.replyMessageToSend(messageToSend, event)
|
return interactionService.replyMessageToSend(messageToSend, event)
|
||||||
.thenApply(interactionHook -> CommandResult.fromSuccess());
|
.thenApply(interactionHook -> CommandResult.fromSuccess());
|
||||||
}
|
}
|
||||||
|
|
||||||
private MessageToSend getDonationMessageToSend() {
|
private MessageToSend getDonationMessageToSend(Long serverId, Integer top, Integer latest) {
|
||||||
BigDecimal currentDonationAmount = donationService.fetchCurrentDonationAmount();
|
DonationsModel donationModel;
|
||||||
DonationsModel donationModel = DonationsModel
|
try {
|
||||||
.builder()
|
DonationsResponse donationResponse = donationService.fetchCurrentDonationAmount(serverId);
|
||||||
.donationAmount(currentDonationAmount)
|
donationModel = donationConverter.convertDonationResponse(donationResponse);
|
||||||
.build();
|
if(top != null) {
|
||||||
|
donationModel.setDonations(donationService.getHighestDonations(donationResponse, top));
|
||||||
|
donationModel.setType(DonationsModel.DonationType.TOP);
|
||||||
|
} else if(latest != null) {
|
||||||
|
donationModel.setType(DonationsModel.DonationType.LATEST);
|
||||||
|
donationModel.setDonations(donationService.getLatestDonations(donationResponse, latest));
|
||||||
|
} else {
|
||||||
|
donationModel.setDonations(new ArrayList<>());
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new AbstractoRunTimeException("Failed to load donation amount.", e);
|
||||||
|
}
|
||||||
return templateService.renderEmbedTemplate(DONATIONS_RESPONSE_TEMPLATE_KEY, donationModel);
|
return templateService.renderEmbedTemplate(DONATIONS_RESPONSE_TEMPLATE_KEY, donationModel);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -77,15 +142,35 @@ public class Donations extends AbstractConditionableCommand {
|
|||||||
.builder()
|
.builder()
|
||||||
.enabled(true)
|
.enabled(true)
|
||||||
.rootCommandName(DebraSlashCommandNames.DEBRA)
|
.rootCommandName(DebraSlashCommandNames.DEBRA)
|
||||||
.commandName("donations")
|
.commandName(DONATIONS_COMMAND_NAME)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
Parameter selectionParameter = Parameter
|
||||||
|
.builder()
|
||||||
|
.templated(true)
|
||||||
|
.name(SELECTION_PARAMETER)
|
||||||
|
.optional(true)
|
||||||
|
.type(String.class)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
|
||||||
|
Parameter selectionValueParameter = Parameter
|
||||||
|
.builder()
|
||||||
|
.templated(true)
|
||||||
|
.name(SELECTION_VALUE_PARAMETER)
|
||||||
|
.optional(true)
|
||||||
|
.type(Integer.class)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
List<Parameter> parameters = Arrays.asList(selectionParameter, selectionValueParameter);
|
||||||
|
|
||||||
return CommandConfiguration.builder()
|
return CommandConfiguration.builder()
|
||||||
.name(DONATIONS_COMMAND_NAME)
|
.name(DONATIONS_COMMAND_NAME)
|
||||||
.module(UtilityModuleDefinition.UTILITY)
|
.module(UtilityModuleDefinition.UTILITY)
|
||||||
.templated(true)
|
.templated(true)
|
||||||
.slashCommandConfig(slashCommandConfig)
|
.slashCommandConfig(slashCommandConfig)
|
||||||
.async(true)
|
.async(true)
|
||||||
|
.parameters(parameters)
|
||||||
.supportsEmbedException(true)
|
.supportsEmbedException(true)
|
||||||
.causesReaction(false)
|
.causesReaction(false)
|
||||||
.help(helpInfo)
|
.help(helpInfo)
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import java.util.List;
|
|||||||
public class DebraFeatureConfig implements FeatureConfig {
|
public class DebraFeatureConfig implements FeatureConfig {
|
||||||
|
|
||||||
public static final String DEBRA_DONATION_NOTIFICATION_DELAY_CONFIG_KEY = "debraDonationNotificationDelayMillis";
|
public static final String DEBRA_DONATION_NOTIFICATION_DELAY_CONFIG_KEY = "debraDonationNotificationDelayMillis";
|
||||||
|
public static final String DEBRA_DONATION_API_FETCH_SIZE_KEY = "debraDonationApiFetchSize";
|
||||||
public static final String DEBRA_DONATION_NOTIFICATION_SERVER_ID_ENV_NAME = "DEBRA_DONATION_NOTIFICATION_SERVER_ID";
|
public static final String DEBRA_DONATION_NOTIFICATION_SERVER_ID_ENV_NAME = "DEBRA_DONATION_NOTIFICATION_SERVER_ID";
|
||||||
@Override
|
@Override
|
||||||
public FeatureDefinition getFeature() {
|
public FeatureDefinition getFeature() {
|
||||||
@@ -25,6 +26,6 @@ public class DebraFeatureConfig implements FeatureConfig {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<String> getRequiredSystemConfigKeys() {
|
public List<String> getRequiredSystemConfigKeys() {
|
||||||
return Arrays.asList(DEBRA_DONATION_NOTIFICATION_DELAY_CONFIG_KEY);
|
return Arrays.asList(DEBRA_DONATION_NOTIFICATION_DELAY_CONFIG_KEY, DEBRA_DONATION_API_FETCH_SIZE_KEY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,5 +11,5 @@ import org.springframework.context.annotation.Configuration;
|
|||||||
@ConfigurationProperties(prefix = "sissi.debra")
|
@ConfigurationProperties(prefix = "sissi.debra")
|
||||||
public class DebraProperties {
|
public class DebraProperties {
|
||||||
private String websocketURL;
|
private String websocketURL;
|
||||||
private String donationsPageURL;
|
private String donationAPIUrl;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
package dev.sheldan.sissi.module.debra.converter;
|
||||||
|
|
||||||
|
import dev.sheldan.sissi.module.debra.model.api.Donation;
|
||||||
|
import dev.sheldan.sissi.module.debra.model.api.DonationsResponse;
|
||||||
|
import dev.sheldan.sissi.module.debra.model.commands.DonationItemModel;
|
||||||
|
import dev.sheldan.sissi.module.debra.model.commands.DonationsModel;
|
||||||
|
import org.apache.commons.lang3.BooleanUtils;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class DonationConverter {
|
||||||
|
public DonationItemModel convertDonation(Donation donation) {
|
||||||
|
return DonationItemModel
|
||||||
|
.builder()
|
||||||
|
.donationAmount(donation.getAmount())
|
||||||
|
.firstName(donation.getFirstname())
|
||||||
|
.lastName(donation.getLastname())
|
||||||
|
.anonymous(BooleanUtils.toBoolean(donation.getAnonym()))
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
public DonationsModel convertDonationResponse(DonationsResponse response) {
|
||||||
|
return DonationsModel
|
||||||
|
.builder()
|
||||||
|
.totalAmount(response.getPage().getCollected())
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,7 +3,7 @@ package dev.sheldan.sissi.module.debra.listener;
|
|||||||
import dev.sheldan.abstracto.core.listener.AsyncStartupListener;
|
import dev.sheldan.abstracto.core.listener.AsyncStartupListener;
|
||||||
import dev.sheldan.abstracto.core.service.ConfigService;
|
import dev.sheldan.abstracto.core.service.ConfigService;
|
||||||
import dev.sheldan.sissi.module.debra.config.DebraProperties;
|
import dev.sheldan.sissi.module.debra.config.DebraProperties;
|
||||||
import dev.sheldan.sissi.module.debra.model.Donation;
|
import dev.sheldan.sissi.module.debra.model.listener.DonationResponseModel;
|
||||||
import dev.sheldan.sissi.module.debra.service.DonationService;
|
import dev.sheldan.sissi.module.debra.service.DonationService;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import okhttp3.*;
|
import okhttp3.*;
|
||||||
@@ -49,7 +49,7 @@ public class WebsocketListener extends WebSocketListener implements AsyncStartup
|
|||||||
log.info("Waiting {} milli seconds to send notification.", delayMillis);
|
log.info("Waiting {} milli seconds to send notification.", delayMillis);
|
||||||
Thread.sleep(delayMillis);
|
Thread.sleep(delayMillis);
|
||||||
log.info("Loading new donation amount and sending notification.");
|
log.info("Loading new donation amount and sending notification.");
|
||||||
Donation donation = donationService.parseDonationFromMessage(text);
|
DonationResponseModel donation = donationService.parseDonationFromMessage(text);
|
||||||
donationService.sendDonationNotification(donation).thenAccept(unused -> {
|
donationService.sendDonationNotification(donation).thenAccept(unused -> {
|
||||||
log.info("Successfully notified about donation.");
|
log.info("Successfully notified about donation.");
|
||||||
}).exceptionally(throwable -> {
|
}).exceptionally(throwable -> {
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
package dev.sheldan.sissi.module.debra.model.api;
|
||||||
|
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@Builder
|
||||||
|
public class Description {
|
||||||
|
private BigDecimal collected;
|
||||||
|
private BigDecimal target;
|
||||||
|
private String currency;
|
||||||
|
private String slug;
|
||||||
|
private String displayName;
|
||||||
|
private BigDecimal collectedNet;
|
||||||
|
private BigDecimal percent;
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
package dev.sheldan.sissi.module.debra.model.api;
|
||||||
|
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@Builder
|
||||||
|
public class Donation {
|
||||||
|
private BigDecimal amount;
|
||||||
|
private String currency;
|
||||||
|
private String text;
|
||||||
|
private Integer anonym;
|
||||||
|
private String firstname;
|
||||||
|
private String lastname;
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package dev.sheldan.sissi.module.debra.model.api;
|
||||||
|
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import java.math.BigInteger;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@Builder
|
||||||
|
public class DonationsResponse {
|
||||||
|
private Description page;
|
||||||
|
private BigInteger donationCount;
|
||||||
|
private List<Donation> donations;
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package dev.sheldan.sissi.module.debra.model.commands;
|
||||||
|
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Builder
|
||||||
|
public class DonationItemModel {
|
||||||
|
private String firstName;
|
||||||
|
private String lastName;
|
||||||
|
private BigDecimal donationAmount;
|
||||||
|
private Boolean anonymous;
|
||||||
|
}
|
||||||
@@ -2,11 +2,21 @@ package dev.sheldan.sissi.module.debra.model.commands;
|
|||||||
|
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
@Builder
|
@Builder
|
||||||
|
@Setter
|
||||||
public class DonationsModel {
|
public class DonationsModel {
|
||||||
private BigDecimal donationAmount;
|
private BigDecimal totalAmount;
|
||||||
|
private DonationType type;
|
||||||
|
private List<DonationItemModel> donations;
|
||||||
|
|
||||||
|
public enum DonationType {
|
||||||
|
LATEST, TOP
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package dev.sheldan.sissi.module.debra.model.listener;
|
package dev.sheldan.sissi.module.debra.model.listener;
|
||||||
|
|
||||||
import dev.sheldan.sissi.module.debra.model.Donation;
|
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
|
||||||
@@ -9,6 +8,6 @@ import java.math.BigDecimal;
|
|||||||
@Getter
|
@Getter
|
||||||
@Builder
|
@Builder
|
||||||
public class DonationNotificationModel {
|
public class DonationNotificationModel {
|
||||||
private Donation donation;
|
private DonationResponseModel donation;
|
||||||
private BigDecimal totalDonationAmount;
|
private BigDecimal totalDonationAmount;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
package dev.sheldan.sissi.module.debra.model;
|
package dev.sheldan.sissi.module.debra.model.listener;
|
||||||
|
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
@@ -9,7 +9,7 @@ import java.math.BigDecimal;
|
|||||||
@Getter
|
@Getter
|
||||||
@Builder
|
@Builder
|
||||||
@ToString
|
@ToString
|
||||||
public class Donation {
|
public class DonationResponseModel {
|
||||||
private String donatorName;
|
private String donatorName;
|
||||||
private BigDecimal amount;
|
private BigDecimal amount;
|
||||||
private String message;
|
private String message;
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
package dev.sheldan.sissi.module.debra.service;
|
||||||
|
|
||||||
|
import com.google.gson.JsonDeserializationContext;
|
||||||
|
import com.google.gson.JsonDeserializer;
|
||||||
|
import com.google.gson.JsonElement;
|
||||||
|
import com.google.gson.JsonParseException;
|
||||||
|
|
||||||
|
import java.lang.reflect.Type;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
|
public class BigDecimalGsonAdapter implements JsonDeserializer<BigDecimal> {
|
||||||
|
@Override
|
||||||
|
public BigDecimal deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
|
||||||
|
try {
|
||||||
|
return new BigDecimal(json.getAsString()
|
||||||
|
.replace(".", "")
|
||||||
|
.replace(',', '.'));
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
throw new JsonParseException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,8 @@
|
|||||||
package dev.sheldan.sissi.module.debra.service;
|
package dev.sheldan.sissi.module.debra.service;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import com.google.gson.GsonBuilder;
|
||||||
|
import dev.sheldan.abstracto.core.service.ConfigService;
|
||||||
import dev.sheldan.abstracto.core.service.PostTargetService;
|
import dev.sheldan.abstracto.core.service.PostTargetService;
|
||||||
import dev.sheldan.abstracto.core.templating.model.MessageToSend;
|
import dev.sheldan.abstracto.core.templating.model.MessageToSend;
|
||||||
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
||||||
@@ -7,25 +10,32 @@ import dev.sheldan.abstracto.core.utils.FutureUtils;
|
|||||||
import dev.sheldan.sissi.module.debra.DonationAmountNotFoundException;
|
import dev.sheldan.sissi.module.debra.DonationAmountNotFoundException;
|
||||||
import dev.sheldan.sissi.module.debra.config.DebraPostTarget;
|
import dev.sheldan.sissi.module.debra.config.DebraPostTarget;
|
||||||
import dev.sheldan.sissi.module.debra.config.DebraProperties;
|
import dev.sheldan.sissi.module.debra.config.DebraProperties;
|
||||||
import dev.sheldan.sissi.module.debra.model.Donation;
|
import dev.sheldan.sissi.module.debra.converter.DonationConverter;
|
||||||
|
import dev.sheldan.sissi.module.debra.model.api.Donation;
|
||||||
|
import dev.sheldan.sissi.module.debra.model.api.DonationsResponse;
|
||||||
|
import dev.sheldan.sissi.module.debra.model.commands.DonationItemModel;
|
||||||
|
import dev.sheldan.sissi.module.debra.model.commands.DonationsModel;
|
||||||
|
import dev.sheldan.sissi.module.debra.model.listener.DonationResponseModel;
|
||||||
import dev.sheldan.sissi.module.debra.model.listener.DonationNotificationModel;
|
import dev.sheldan.sissi.module.debra.model.listener.DonationNotificationModel;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import net.dv8tion.jda.api.entities.Message;
|
import net.dv8tion.jda.api.entities.Message;
|
||||||
|
import okhttp3.OkHttpClient;
|
||||||
|
import okhttp3.Request;
|
||||||
|
import okhttp3.Response;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.InputStreamReader;
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.net.URL;
|
import java.util.Comparator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import static dev.sheldan.sissi.module.debra.config.DebraFeatureConfig.DEBRA_DONATION_API_FETCH_SIZE_KEY;
|
||||||
import static dev.sheldan.sissi.module.debra.config.DebraFeatureConfig.DEBRA_DONATION_NOTIFICATION_SERVER_ID_ENV_NAME;
|
import static dev.sheldan.sissi.module.debra.config.DebraFeatureConfig.DEBRA_DONATION_NOTIFICATION_SERVER_ID_ENV_NAME;
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
@@ -41,19 +51,27 @@ public class DonationService {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private TemplateService templateService;
|
private TemplateService templateService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private OkHttpClient okHttpClient;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private DonationConverter donationConverter;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ConfigService configService;
|
||||||
|
|
||||||
private static final String DEBRA_DONATION_NOTIFICATION_TEMPLATE_KEY = "debra_donation_notification";
|
private static final String DEBRA_DONATION_NOTIFICATION_TEMPLATE_KEY = "debra_donation_notification";
|
||||||
|
|
||||||
private static final Pattern MESSAGE_PATTERN = Pattern.compile("(.*) hat (\\d{1,9},\\d{2}) Euro gespendet!<br \\/>Vielen Dank!<br \\/>Nachricht:<br \\/>(.*)");
|
private static final Pattern MESSAGE_PATTERN = Pattern.compile("(.*) hat (\\d{1,9},\\d{2}) Euro gespendet!<br \\/>Vielen Dank!<br \\/>Nachricht:<br \\/>(.*)");
|
||||||
private static final Pattern DONATION_PAGE_AMOUNT_PARTNER = Pattern.compile("\"metric4\",\\s*\"(.*)\"");
|
|
||||||
|
|
||||||
public Donation parseDonationFromMessage(String message) {
|
public DonationResponseModel parseDonationFromMessage(String message) {
|
||||||
Matcher matcher = MESSAGE_PATTERN.matcher(message);
|
Matcher matcher = MESSAGE_PATTERN.matcher(message);
|
||||||
if (matcher.find()) {
|
if (matcher.find()) {
|
||||||
String donatorName = matcher.group(1);
|
String donatorName = matcher.group(1);
|
||||||
String amountString = matcher.group(2);
|
String amountString = matcher.group(2);
|
||||||
BigDecimal amount = new BigDecimal(amountString.replace(',', '.'));
|
BigDecimal amount = new BigDecimal(amountString.replace(',', '.'));
|
||||||
String donationMessage = Optional.ofNullable(matcher.group(3)).map(msg -> msg.replaceAll("(<br>)+", " ")).map(String::trim).orElse("");
|
String donationMessage = Optional.ofNullable(matcher.group(3)).map(msg -> msg.replaceAll("(<br>)+", " ")).map(String::trim).orElse("");
|
||||||
return Donation
|
return DonationResponseModel
|
||||||
.builder()
|
.builder()
|
||||||
.message(donationMessage)
|
.message(donationMessage)
|
||||||
.donatorName(donatorName)
|
.donatorName(donatorName)
|
||||||
@@ -64,32 +82,67 @@ public class DonationService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public BigDecimal fetchCurrentDonationAmount() {
|
public List<DonationItemModel> getHighestDonations(DonationsResponse response, Integer maxCount) {
|
||||||
try (InputStream is = new URL(debraProperties.getDonationsPageURL()).openStream()) {
|
List<Donation> topDonations = response
|
||||||
BufferedReader br = new BufferedReader(new InputStreamReader(is));
|
.getDonations()
|
||||||
String line;
|
.stream()
|
||||||
while ((line = br.readLine()) != null) {
|
.sorted(Comparator.comparing(Donation::getAmount)
|
||||||
Matcher matcher = DONATION_PAGE_AMOUNT_PARTNER.matcher(line);
|
.reversed())
|
||||||
if (matcher.find()) {
|
.collect(Collectors.toList());
|
||||||
return new BigDecimal(matcher.group(1).replace(',', '.'));
|
return topDonations
|
||||||
}
|
.stream()
|
||||||
}
|
.limit(maxCount)
|
||||||
log.warn("Did not find the donation amount in the configured URL {}", debraProperties.getDonationsPageURL());
|
.map(donation -> donationConverter.convertDonation(donation))
|
||||||
throw new DonationAmountNotFoundException();
|
.collect(Collectors.toList());
|
||||||
} catch (IOException ex) {
|
|
||||||
log.warn("Failed to load page for parsing donation amount {}.", debraProperties.getDonationsPageURL(), ex);
|
|
||||||
throw new DonationAmountNotFoundException();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public CompletableFuture<Void> sendDonationNotification(Donation donation) {
|
public List<DonationItemModel> getLatestDonations(DonationsResponse response, Integer maxCount) {
|
||||||
|
return response
|
||||||
|
.getDonations()
|
||||||
|
.stream()
|
||||||
|
.limit(maxCount)
|
||||||
|
.map(donation -> donationConverter.convertDonation(donation))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
public DonationsResponse fetchCurrentDonationAmount(Long serverId) throws IOException {
|
||||||
|
Long fetchSize = configService.getLongValueOrConfigDefault(DEBRA_DONATION_API_FETCH_SIZE_KEY, serverId);
|
||||||
|
Request request = new Request.Builder()
|
||||||
|
.url(String.format(debraProperties.getDonationAPIUrl(), fetchSize))
|
||||||
|
.get()
|
||||||
|
.build();
|
||||||
|
Response response = okHttpClient.newCall(request).execute();
|
||||||
|
if(!response.isSuccessful()) {
|
||||||
|
if (log.isDebugEnabled()) {
|
||||||
|
log.error("Failed to retrieve urban dictionary definition. Response had code {} with body {}.",
|
||||||
|
response.code(), response.body());
|
||||||
|
}
|
||||||
|
throw new DonationAmountNotFoundException();
|
||||||
|
}
|
||||||
|
Gson gson = getGson();
|
||||||
|
|
||||||
|
return gson.fromJson(response.body().string(), DonationsResponse.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Gson getGson() {
|
||||||
|
return new GsonBuilder()
|
||||||
|
.registerTypeAdapter(BigDecimal.class, new BigDecimalGsonAdapter())
|
||||||
|
.create();
|
||||||
|
}
|
||||||
|
|
||||||
|
private DonationsModel getDonationInfoModel(Long serverId) throws IOException {
|
||||||
|
return donationConverter.convertDonationResponse(fetchCurrentDonationAmount(serverId));
|
||||||
|
}
|
||||||
|
|
||||||
|
public CompletableFuture<Void> sendDonationNotification(DonationResponseModel donation) throws IOException {
|
||||||
|
Long targetServerId = Long.parseLong(System.getenv(DEBRA_DONATION_NOTIFICATION_SERVER_ID_ENV_NAME));
|
||||||
|
DonationsModel donationInfoModel = getDonationInfoModel(targetServerId);
|
||||||
DonationNotificationModel model = DonationNotificationModel
|
DonationNotificationModel model = DonationNotificationModel
|
||||||
.builder()
|
.builder()
|
||||||
.donation(donation)
|
.donation(donation)
|
||||||
.totalDonationAmount(fetchCurrentDonationAmount())
|
.totalDonationAmount(donationInfoModel.getTotalAmount())
|
||||||
.build();
|
.build();
|
||||||
MessageToSend messageToSend = templateService.renderEmbedTemplate(DEBRA_DONATION_NOTIFICATION_TEMPLATE_KEY, model);
|
MessageToSend messageToSend = templateService.renderEmbedTemplate(DEBRA_DONATION_NOTIFICATION_TEMPLATE_KEY, model);
|
||||||
Long targetServerId = Long.parseLong(System.getenv(DEBRA_DONATION_NOTIFICATION_SERVER_ID_ENV_NAME));
|
|
||||||
List<CompletableFuture<Message>> firstMessage = postTargetService.sendEmbedInPostTarget(messageToSend, DebraPostTarget.DEBRA_DONATION_NOTIFICATION, targetServerId);
|
List<CompletableFuture<Message>> firstMessage = postTargetService.sendEmbedInPostTarget(messageToSend, DebraPostTarget.DEBRA_DONATION_NOTIFICATION, targetServerId);
|
||||||
List<CompletableFuture<Message>> secondMessage = postTargetService.sendEmbedInPostTarget(messageToSend, DebraPostTarget.DEBRA_DONATION_NOTIFICATION2, targetServerId);
|
List<CompletableFuture<Message>> secondMessage = postTargetService.sendEmbedInPostTarget(messageToSend, DebraPostTarget.DEBRA_DONATION_NOTIFICATION2, targetServerId);
|
||||||
firstMessage.addAll(secondMessage);
|
firstMessage.addAll(secondMessage);
|
||||||
|
|||||||
@@ -5,7 +5,10 @@ abstracto.postTargets.debraDonationNotification.name=debraDonationNotification
|
|||||||
abstracto.postTargets.debraDonationNotification2.name=debraDonationNotification2
|
abstracto.postTargets.debraDonationNotification2.name=debraDonationNotification2
|
||||||
|
|
||||||
sissi.debra.websocketURL=ws://spenden.baba.fm:8765/
|
sissi.debra.websocketURL=ws://spenden.baba.fm:8765/
|
||||||
sissi.debra.donationsPageURL=https://em.altruja.de/discord-fuer-debra-2022
|
sissi.debra.donationAPIUrl=https://www.altruja.de/api/page/discord-fuer-debra-2022?details=1&num=%s&ort=0
|
||||||
|
|
||||||
abstracto.systemConfigs.debraDonationNotificationDelayMillis.name=debraDonationNotificationDelayMillis
|
abstracto.systemConfigs.debraDonationNotificationDelayMillis.name=debraDonationNotificationDelayMillis
|
||||||
abstracto.systemConfigs.debraDonationNotificationDelayMillis.longValue=60000
|
abstracto.systemConfigs.debraDonationNotificationDelayMillis.longValue=60000
|
||||||
|
|
||||||
|
abstracto.systemConfigs.debraDonationApiFetchSize.name=debraDonationApiFetchSize
|
||||||
|
abstracto.systemConfigs.debraDonationApiFetchSize.longValue=1000
|
||||||
@@ -31,4 +31,4 @@ DEBRA_DONATION_NOTIFICATION_SERVER_ID=0
|
|||||||
PGADMIN_DEFAULT_PASSWORD=admin
|
PGADMIN_DEFAULT_PASSWORD=admin
|
||||||
TOKEN=<INSERT TOKEN>
|
TOKEN=<INSERT TOKEN>
|
||||||
YOUTUBE_API_KEY=<INSERT KEY>
|
YOUTUBE_API_KEY=<INSERT KEY>
|
||||||
SISSI_VERSION=1.3.15
|
SISSI_VERSION=1.3.16
|
||||||
@@ -1,10 +1,26 @@
|
|||||||
{
|
{
|
||||||
<#assign donationAmount=donationAmount>
|
<#assign donationAmount=totalAmount>
|
||||||
<#setting locale="de_DE">
|
<#setting locale="de_DE">
|
||||||
"additionalMessage": "<#include "donations_response_description">",
|
"additionalMessage": "<#include "donations_response_description">",
|
||||||
"embeds": [
|
"embeds": [
|
||||||
{
|
{
|
||||||
"imageUrl": "https://cdn.discordapp.com/attachments/299115929206390784/1047306670319079474/dotpict-1.png"
|
"imageUrl": "https://cdn.discordapp.com/attachments/299115929206390784/1047306670319079474/dotpict-1.png"
|
||||||
|
<#if donations?size gt 0>
|
||||||
|
,<#if type.name() == "LATEST">
|
||||||
|
"description": "<#include "donations_response_latest_donations_description">"
|
||||||
|
<#else>
|
||||||
|
"description": "<#include "donations_response_top_donations_description">"
|
||||||
|
</#if>
|
||||||
|
,"fields": [
|
||||||
|
<#list donations as donation>
|
||||||
|
{
|
||||||
|
"name": "<#if donation.anonymous><#include "donations_response_anonymous"><#else>${donation.firstName}</#if>",
|
||||||
|
"value": "${donation.donationAmount}€",
|
||||||
|
"inline": true
|
||||||
|
}
|
||||||
|
<#sep>,</#list>
|
||||||
|
]
|
||||||
|
</#if>
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
Anonym
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
Das hier sind die neuesten Spenden:
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
Das hier sind die höchsten Spenden:
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
The amount of donations you want to load for the specified type. Defaults to 5, max 20.
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
Type of donations you want to load, either 'top' or 'latest'. Default 'latest' for any other value
|
||||||
Reference in New Issue
Block a user