diff --git a/application/sissi-modules/debra/pom.xml b/application/sissi-modules/debra/pom.xml index 36628291..043ebbfe 100644 --- a/application/sissi-modules/debra/pom.xml +++ b/application/sissi-modules/debra/pom.xml @@ -10,6 +10,13 @@ dev.sheldan.sissi.application.module debra + + + com.google.code.gson + gson + + + diff --git a/application/sissi-modules/debra/src/main/java/dev/sheldan/sissi/module/debra/commands/Donations.java b/application/sissi-modules/debra/src/main/java/dev/sheldan/sissi/module/debra/commands/Donations.java index 3d51cb9b..95335ed1 100644 --- a/application/sissi-modules/debra/src/main/java/dev/sheldan/sissi/module/debra/commands/Donations.java +++ b/application/sissi-modules/debra/src/main/java/dev/sheldan/sissi/module/debra/commands/Donations.java @@ -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.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.config.FeatureDefinition; +import dev.sheldan.abstracto.core.exception.AbstractoRunTimeException; import dev.sheldan.abstracto.core.interaction.InteractionService; 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.templating.model.MessageToSend; import dev.sheldan.abstracto.core.templating.service.TemplateService; import dev.sheldan.abstracto.core.utils.FutureUtils; import dev.sheldan.sissi.module.debra.config.DebraFeatureDefinition; 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.service.DonationService; import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent; import org.springframework.beans.factory.annotation.Autowired; 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; @@ -30,6 +38,8 @@ public class Donations extends AbstractConditionableCommand { private static final String DONATIONS_COMMAND_NAME = "donations"; 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 private ChannelService channelService; @@ -43,26 +53,81 @@ public class Donations extends AbstractConditionableCommand { @Autowired private TemplateService templateService; + @Autowired + private DonationConverter donationConverter; + + @Autowired + private SlashCommandParameterService slashCommandParameterService; + @Override public CompletableFuture executeAsync(CommandContext commandContext) { - MessageToSend messageToSend = getDonationMessageToSend(); + List 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())) .thenApply(unused -> CommandResult.fromSuccess()); } @Override public CompletableFuture 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) .thenApply(interactionHook -> CommandResult.fromSuccess()); } - private MessageToSend getDonationMessageToSend() { - BigDecimal currentDonationAmount = donationService.fetchCurrentDonationAmount(); - DonationsModel donationModel = DonationsModel - .builder() - .donationAmount(currentDonationAmount) - .build(); + private MessageToSend getDonationMessageToSend(Long serverId, Integer top, Integer latest) { + DonationsModel donationModel; + try { + DonationsResponse donationResponse = donationService.fetchCurrentDonationAmount(serverId); + donationModel = donationConverter.convertDonationResponse(donationResponse); + 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); } @@ -77,15 +142,35 @@ public class Donations extends AbstractConditionableCommand { .builder() .enabled(true) .rootCommandName(DebraSlashCommandNames.DEBRA) - .commandName("donations") + .commandName(DONATIONS_COMMAND_NAME) .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 parameters = Arrays.asList(selectionParameter, selectionValueParameter); + return CommandConfiguration.builder() .name(DONATIONS_COMMAND_NAME) .module(UtilityModuleDefinition.UTILITY) .templated(true) .slashCommandConfig(slashCommandConfig) .async(true) + .parameters(parameters) .supportsEmbedException(true) .causesReaction(false) .help(helpInfo) diff --git a/application/sissi-modules/debra/src/main/java/dev/sheldan/sissi/module/debra/config/DebraFeatureConfig.java b/application/sissi-modules/debra/src/main/java/dev/sheldan/sissi/module/debra/config/DebraFeatureConfig.java index 1830c467..69651ecd 100644 --- a/application/sissi-modules/debra/src/main/java/dev/sheldan/sissi/module/debra/config/DebraFeatureConfig.java +++ b/application/sissi-modules/debra/src/main/java/dev/sheldan/sissi/module/debra/config/DebraFeatureConfig.java @@ -12,6 +12,7 @@ import java.util.List; public class DebraFeatureConfig implements FeatureConfig { 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"; @Override public FeatureDefinition getFeature() { @@ -25,6 +26,6 @@ public class DebraFeatureConfig implements FeatureConfig { @Override public List 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); } } diff --git a/application/sissi-modules/debra/src/main/java/dev/sheldan/sissi/module/debra/config/DebraProperties.java b/application/sissi-modules/debra/src/main/java/dev/sheldan/sissi/module/debra/config/DebraProperties.java index 94aba4ac..aa095e54 100644 --- a/application/sissi-modules/debra/src/main/java/dev/sheldan/sissi/module/debra/config/DebraProperties.java +++ b/application/sissi-modules/debra/src/main/java/dev/sheldan/sissi/module/debra/config/DebraProperties.java @@ -11,5 +11,5 @@ import org.springframework.context.annotation.Configuration; @ConfigurationProperties(prefix = "sissi.debra") public class DebraProperties { private String websocketURL; - private String donationsPageURL; + private String donationAPIUrl; } diff --git a/application/sissi-modules/debra/src/main/java/dev/sheldan/sissi/module/debra/converter/DonationConverter.java b/application/sissi-modules/debra/src/main/java/dev/sheldan/sissi/module/debra/converter/DonationConverter.java new file mode 100644 index 00000000..52fda6b9 --- /dev/null +++ b/application/sissi-modules/debra/src/main/java/dev/sheldan/sissi/module/debra/converter/DonationConverter.java @@ -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(); + } +} diff --git a/application/sissi-modules/debra/src/main/java/dev/sheldan/sissi/module/debra/listener/WebsocketListener.java b/application/sissi-modules/debra/src/main/java/dev/sheldan/sissi/module/debra/listener/WebsocketListener.java index c430f122..e79abddd 100644 --- a/application/sissi-modules/debra/src/main/java/dev/sheldan/sissi/module/debra/listener/WebsocketListener.java +++ b/application/sissi-modules/debra/src/main/java/dev/sheldan/sissi/module/debra/listener/WebsocketListener.java @@ -3,7 +3,7 @@ package dev.sheldan.sissi.module.debra.listener; import dev.sheldan.abstracto.core.listener.AsyncStartupListener; import dev.sheldan.abstracto.core.service.ConfigService; 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 lombok.extern.slf4j.Slf4j; import okhttp3.*; @@ -49,7 +49,7 @@ public class WebsocketListener extends WebSocketListener implements AsyncStartup log.info("Waiting {} milli seconds to send notification.", delayMillis); Thread.sleep(delayMillis); log.info("Loading new donation amount and sending notification."); - Donation donation = donationService.parseDonationFromMessage(text); + DonationResponseModel donation = donationService.parseDonationFromMessage(text); donationService.sendDonationNotification(donation).thenAccept(unused -> { log.info("Successfully notified about donation."); }).exceptionally(throwable -> { diff --git a/application/sissi-modules/debra/src/main/java/dev/sheldan/sissi/module/debra/model/api/Description.java b/application/sissi-modules/debra/src/main/java/dev/sheldan/sissi/module/debra/model/api/Description.java new file mode 100644 index 00000000..00b89259 --- /dev/null +++ b/application/sissi-modules/debra/src/main/java/dev/sheldan/sissi/module/debra/model/api/Description.java @@ -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; +} diff --git a/application/sissi-modules/debra/src/main/java/dev/sheldan/sissi/module/debra/model/api/Donation.java b/application/sissi-modules/debra/src/main/java/dev/sheldan/sissi/module/debra/model/api/Donation.java new file mode 100644 index 00000000..8c6d6bcd --- /dev/null +++ b/application/sissi-modules/debra/src/main/java/dev/sheldan/sissi/module/debra/model/api/Donation.java @@ -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; +} diff --git a/application/sissi-modules/debra/src/main/java/dev/sheldan/sissi/module/debra/model/api/DonationsResponse.java b/application/sissi-modules/debra/src/main/java/dev/sheldan/sissi/module/debra/model/api/DonationsResponse.java new file mode 100644 index 00000000..8a1fdb97 --- /dev/null +++ b/application/sissi-modules/debra/src/main/java/dev/sheldan/sissi/module/debra/model/api/DonationsResponse.java @@ -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 donations; +} diff --git a/application/sissi-modules/debra/src/main/java/dev/sheldan/sissi/module/debra/model/commands/DonationItemModel.java b/application/sissi-modules/debra/src/main/java/dev/sheldan/sissi/module/debra/model/commands/DonationItemModel.java new file mode 100644 index 00000000..2ddb6340 --- /dev/null +++ b/application/sissi-modules/debra/src/main/java/dev/sheldan/sissi/module/debra/model/commands/DonationItemModel.java @@ -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; +} diff --git a/application/sissi-modules/debra/src/main/java/dev/sheldan/sissi/module/debra/model/commands/DonationsModel.java b/application/sissi-modules/debra/src/main/java/dev/sheldan/sissi/module/debra/model/commands/DonationsModel.java index 633c3776..6eb0a3dd 100644 --- a/application/sissi-modules/debra/src/main/java/dev/sheldan/sissi/module/debra/model/commands/DonationsModel.java +++ b/application/sissi-modules/debra/src/main/java/dev/sheldan/sissi/module/debra/model/commands/DonationsModel.java @@ -2,11 +2,21 @@ package dev.sheldan.sissi.module.debra.model.commands; import lombok.Builder; import lombok.Getter; +import lombok.Setter; import java.math.BigDecimal; +import java.util.List; @Getter @Builder +@Setter public class DonationsModel { - private BigDecimal donationAmount; + private BigDecimal totalAmount; + private DonationType type; + private List donations; + + public enum DonationType { + LATEST, TOP + } + } diff --git a/application/sissi-modules/debra/src/main/java/dev/sheldan/sissi/module/debra/model/listener/DonationNotificationModel.java b/application/sissi-modules/debra/src/main/java/dev/sheldan/sissi/module/debra/model/listener/DonationNotificationModel.java index 1c5e6ae1..f0aac44e 100644 --- a/application/sissi-modules/debra/src/main/java/dev/sheldan/sissi/module/debra/model/listener/DonationNotificationModel.java +++ b/application/sissi-modules/debra/src/main/java/dev/sheldan/sissi/module/debra/model/listener/DonationNotificationModel.java @@ -1,6 +1,5 @@ package dev.sheldan.sissi.module.debra.model.listener; -import dev.sheldan.sissi.module.debra.model.Donation; import lombok.Builder; import lombok.Getter; @@ -9,6 +8,6 @@ import java.math.BigDecimal; @Getter @Builder public class DonationNotificationModel { - private Donation donation; + private DonationResponseModel donation; private BigDecimal totalDonationAmount; } diff --git a/application/sissi-modules/debra/src/main/java/dev/sheldan/sissi/module/debra/model/Donation.java b/application/sissi-modules/debra/src/main/java/dev/sheldan/sissi/module/debra/model/listener/DonationResponseModel.java similarity index 70% rename from application/sissi-modules/debra/src/main/java/dev/sheldan/sissi/module/debra/model/Donation.java rename to application/sissi-modules/debra/src/main/java/dev/sheldan/sissi/module/debra/model/listener/DonationResponseModel.java index 15e614ba..996f307c 100644 --- a/application/sissi-modules/debra/src/main/java/dev/sheldan/sissi/module/debra/model/Donation.java +++ b/application/sissi-modules/debra/src/main/java/dev/sheldan/sissi/module/debra/model/listener/DonationResponseModel.java @@ -1,4 +1,4 @@ -package dev.sheldan.sissi.module.debra.model; +package dev.sheldan.sissi.module.debra.model.listener; import lombok.Builder; import lombok.Getter; @@ -9,7 +9,7 @@ import java.math.BigDecimal; @Getter @Builder @ToString -public class Donation { +public class DonationResponseModel { private String donatorName; private BigDecimal amount; private String message; diff --git a/application/sissi-modules/debra/src/main/java/dev/sheldan/sissi/module/debra/service/BigDecimalGsonAdapter.java b/application/sissi-modules/debra/src/main/java/dev/sheldan/sissi/module/debra/service/BigDecimalGsonAdapter.java new file mode 100644 index 00000000..2b07323f --- /dev/null +++ b/application/sissi-modules/debra/src/main/java/dev/sheldan/sissi/module/debra/service/BigDecimalGsonAdapter.java @@ -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 { + @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); + } + } +} diff --git a/application/sissi-modules/debra/src/main/java/dev/sheldan/sissi/module/debra/service/DonationService.java b/application/sissi-modules/debra/src/main/java/dev/sheldan/sissi/module/debra/service/DonationService.java index a5c1c59f..a53079c1 100644 --- a/application/sissi-modules/debra/src/main/java/dev/sheldan/sissi/module/debra/service/DonationService.java +++ b/application/sissi-modules/debra/src/main/java/dev/sheldan/sissi/module/debra/service/DonationService.java @@ -1,5 +1,8 @@ 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.templating.model.MessageToSend; 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.config.DebraPostTarget; 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 lombok.extern.slf4j.Slf4j; 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.stereotype.Component; -import java.io.BufferedReader; import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; import java.math.BigDecimal; -import java.net.URL; +import java.util.Comparator; import java.util.List; import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.regex.Matcher; 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; @Component @@ -41,19 +51,27 @@ public class DonationService { @Autowired 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 Pattern MESSAGE_PATTERN = Pattern.compile("(.*) hat (\\d{1,9},\\d{2}) Euro gespendet!
Vielen Dank!
Nachricht:
(.*)"); - 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); if (matcher.find()) { String donatorName = matcher.group(1); String amountString = matcher.group(2); BigDecimal amount = new BigDecimal(amountString.replace(',', '.')); String donationMessage = Optional.ofNullable(matcher.group(3)).map(msg -> msg.replaceAll("(
)+", " ")).map(String::trim).orElse(""); - return Donation + return DonationResponseModel .builder() .message(donationMessage) .donatorName(donatorName) @@ -64,32 +82,67 @@ public class DonationService { } } - public BigDecimal fetchCurrentDonationAmount() { - try (InputStream is = new URL(debraProperties.getDonationsPageURL()).openStream()) { - BufferedReader br = new BufferedReader(new InputStreamReader(is)); - String line; - while ((line = br.readLine()) != null) { - Matcher matcher = DONATION_PAGE_AMOUNT_PARTNER.matcher(line); - if (matcher.find()) { - return new BigDecimal(matcher.group(1).replace(',', '.')); - } - } - log.warn("Did not find the donation amount in the configured URL {}", debraProperties.getDonationsPageURL()); - throw new DonationAmountNotFoundException(); - } catch (IOException ex) { - log.warn("Failed to load page for parsing donation amount {}.", debraProperties.getDonationsPageURL(), ex); - throw new DonationAmountNotFoundException(); - } + public List getHighestDonations(DonationsResponse response, Integer maxCount) { + List topDonations = response + .getDonations() + .stream() + .sorted(Comparator.comparing(Donation::getAmount) + .reversed()) + .collect(Collectors.toList()); + return topDonations + .stream() + .limit(maxCount) + .map(donation -> donationConverter.convertDonation(donation)) + .collect(Collectors.toList()); } - public CompletableFuture sendDonationNotification(Donation donation) { + public List 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 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 .builder() .donation(donation) - .totalDonationAmount(fetchCurrentDonationAmount()) + .totalDonationAmount(donationInfoModel.getTotalAmount()) .build(); MessageToSend messageToSend = templateService.renderEmbedTemplate(DEBRA_DONATION_NOTIFICATION_TEMPLATE_KEY, model); - Long targetServerId = Long.parseLong(System.getenv(DEBRA_DONATION_NOTIFICATION_SERVER_ID_ENV_NAME)); List> firstMessage = postTargetService.sendEmbedInPostTarget(messageToSend, DebraPostTarget.DEBRA_DONATION_NOTIFICATION, targetServerId); List> secondMessage = postTargetService.sendEmbedInPostTarget(messageToSend, DebraPostTarget.DEBRA_DONATION_NOTIFICATION2, targetServerId); firstMessage.addAll(secondMessage); diff --git a/application/sissi-modules/debra/src/main/resources/debra.properties b/application/sissi-modules/debra/src/main/resources/debra.properties index 10adf11c..02df9920 100644 --- a/application/sissi-modules/debra/src/main/resources/debra.properties +++ b/application/sissi-modules/debra/src/main/resources/debra.properties @@ -5,7 +5,10 @@ abstracto.postTargets.debraDonationNotification.name=debraDonationNotification abstracto.postTargets.debraDonationNotification2.name=debraDonationNotification2 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.longValue=60000 \ No newline at end of file +abstracto.systemConfigs.debraDonationNotificationDelayMillis.longValue=60000 + +abstracto.systemConfigs.debraDonationApiFetchSize.name=debraDonationApiFetchSize +abstracto.systemConfigs.debraDonationApiFetchSize.longValue=1000 \ No newline at end of file diff --git a/deployment/docker-compose/src/main/resources/.env b/deployment/docker-compose/src/main/resources/.env index be3492f2..441dc302 100644 --- a/deployment/docker-compose/src/main/resources/.env +++ b/deployment/docker-compose/src/main/resources/.env @@ -31,4 +31,4 @@ DEBRA_DONATION_NOTIFICATION_SERVER_ID=0 PGADMIN_DEFAULT_PASSWORD=admin TOKEN= YOUTUBE_API_KEY= -SISSI_VERSION=1.3.15 \ No newline at end of file +SISSI_VERSION=1.3.16 \ No newline at end of file diff --git a/templates/sissi-templates/module-templates/debra-templates/src/main/resources/en_US/commands/donations/donations_response_embed_en_US.ftl b/templates/sissi-templates/module-templates/debra-templates/src/main/resources/en_US/commands/donations/donations_response_embed_en_US.ftl index 944b8918..27f00976 100644 --- a/templates/sissi-templates/module-templates/debra-templates/src/main/resources/en_US/commands/donations/donations_response_embed_en_US.ftl +++ b/templates/sissi-templates/module-templates/debra-templates/src/main/resources/en_US/commands/donations/donations_response_embed_en_US.ftl @@ -1,10 +1,26 @@ { - <#assign donationAmount=donationAmount> + <#assign donationAmount=totalAmount> <#setting locale="de_DE"> "additionalMessage": "<#include "donations_response_description">", "embeds": [ { "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">" + + ,"fields": [ + <#list donations as donation> + { + "name": "<#if donation.anonymous><#include "donations_response_anonymous"><#else>${donation.firstName}", + "value": "${donation.donationAmount}€", + "inline": true + } + <#sep>, + ] + } ] } \ No newline at end of file diff --git a/templates/sissi-translations/module-translations/debra-translations/src/main/resources/de_DE/commands/donations/donations_response_anonymous_de_DE.ftl b/templates/sissi-translations/module-translations/debra-translations/src/main/resources/de_DE/commands/donations/donations_response_anonymous_de_DE.ftl new file mode 100644 index 00000000..ab464fe4 --- /dev/null +++ b/templates/sissi-translations/module-translations/debra-translations/src/main/resources/de_DE/commands/donations/donations_response_anonymous_de_DE.ftl @@ -0,0 +1 @@ +Anonym \ No newline at end of file diff --git a/templates/sissi-translations/module-translations/debra-translations/src/main/resources/de_DE/commands/donations/donations_response_latest_donations_description_de_DE.ftl b/templates/sissi-translations/module-translations/debra-translations/src/main/resources/de_DE/commands/donations/donations_response_latest_donations_description_de_DE.ftl new file mode 100644 index 00000000..b109c181 --- /dev/null +++ b/templates/sissi-translations/module-translations/debra-translations/src/main/resources/de_DE/commands/donations/donations_response_latest_donations_description_de_DE.ftl @@ -0,0 +1 @@ +Das hier sind die neuesten Spenden: \ No newline at end of file diff --git a/templates/sissi-translations/module-translations/debra-translations/src/main/resources/de_DE/commands/donations/donations_response_top_donations_description_de_DE.ftl b/templates/sissi-translations/module-translations/debra-translations/src/main/resources/de_DE/commands/donations/donations_response_top_donations_description_de_DE.ftl new file mode 100644 index 00000000..d0624fa6 --- /dev/null +++ b/templates/sissi-translations/module-translations/debra-translations/src/main/resources/de_DE/commands/donations/donations_response_top_donations_description_de_DE.ftl @@ -0,0 +1 @@ +Das hier sind die höchsten Spenden: \ No newline at end of file diff --git a/templates/sissi-translations/module-translations/debra-translations/src/main/resources/en_US/commands/donations/help/donations_parameter_parametervalue_en_US.ftl b/templates/sissi-translations/module-translations/debra-translations/src/main/resources/en_US/commands/donations/help/donations_parameter_parametervalue_en_US.ftl new file mode 100644 index 00000000..6b59bc19 --- /dev/null +++ b/templates/sissi-translations/module-translations/debra-translations/src/main/resources/en_US/commands/donations/help/donations_parameter_parametervalue_en_US.ftl @@ -0,0 +1 @@ +The amount of donations you want to load for the specified type. Defaults to 5, max 20. \ No newline at end of file diff --git a/templates/sissi-translations/module-translations/debra-translations/src/main/resources/en_US/commands/donations/help/donations_parameter_type_en_US.ftl b/templates/sissi-translations/module-translations/debra-translations/src/main/resources/en_US/commands/donations/help/donations_parameter_type_en_US.ftl new file mode 100644 index 00000000..94e449df --- /dev/null +++ b/templates/sissi-translations/module-translations/debra-translations/src/main/resources/en_US/commands/donations/help/donations_parameter_type_en_US.ftl @@ -0,0 +1 @@ +Type of donations you want to load, either 'top' or 'latest'. Default 'latest' for any other value \ No newline at end of file