Compare commits

...

24 Commits

Author SHA1 Message Date
Sheldan
a47f399d36 [SIS-xxx] slight adaptions for new donation structure 2025-12-07 13:40:52 +01:00
release-bot
29bb752367 Commit from GitHub Actions (Publishes a new version of Sissi) 2025-11-29 13:31:18 +00:00
release-bot
efdb375a83 [maven-release-plugin] prepare for next development iteration 2025-11-29 13:25:49 +00:00
release-bot
f158580897 [maven-release-plugin] prepare release sissi-1.5.16 2025-11-29 13:25:48 +00:00
Sheldan
4411995e65 [SIS-xxx] abstracto upgrade 2025-11-29 14:22:13 +01:00
Sheldan
c9b5258798 [SIS-xxx] changing the setup for donation tracking 2025-11-29 14:21:48 +01:00
Sheldan
ea5a7509bc [SIS-xxx] re-ordering title in leave message 2025-11-27 20:39:02 +01:00
Sheldan
40703005e1 [SIS-xxx] updating join and leave embeds to work with default template 2025-11-23 15:33:06 +01:00
Sheldan
fe036d7010 [SIS-xxx] removing empty spaces and formatting the id better 2025-11-13 00:57:03 +01:00
release-bot
2547d68dfc Commit from GitHub Actions (Publishes a new version of Sissi) 2025-11-12 23:27:53 +00:00
release-bot
b8b59b09c4 [maven-release-plugin] prepare for next development iteration 2025-11-12 23:20:46 +00:00
release-bot
774c142238 [maven-release-plugin] prepare release sissi-1.5.15 2025-11-12 23:20:45 +00:00
Sheldan
5b6160b0d2 [SIS-xxx] upgrading abstracto version
adding custom template for leave message
updating template to fit new leave model
2025-11-13 00:11:01 +01:00
release-bot
453b2214cd Commit from GitHub Actions (Publishes a new version of Sissi) 2025-10-12 18:42:28 +00:00
release-bot
071c603e54 [maven-release-plugin] prepare for next development iteration 2025-10-12 18:37:06 +00:00
release-bot
31538747f5 [maven-release-plugin] prepare release sissi-1.5.14 2025-10-12 18:37:05 +00:00
Sheldan
afb11dc74a [SIS-xxx] upgrading abstracto version 2025-10-12 20:19:40 +02:00
Sheldan
dd5bb63962 [SIS-xxx] fixing meetup display without location 2025-10-03 18:13:58 +02:00
release-bot
28da63db37 Commit from GitHub Actions (Publishes a new version of Sissi) 2025-09-10 23:23:31 +00:00
release-bot
18755afb57 [maven-release-plugin] prepare for next development iteration 2025-09-10 23:16:17 +00:00
release-bot
ccfb64324e [maven-release-plugin] prepare release sissi-1.5.13 2025-09-10 23:16:15 +00:00
Sheldan
d33ce3da6c [SIS-xxx] upgrading abstracto version 2025-09-11 01:11:14 +02:00
release-bot
16553e0299 Commit from GitHub Actions (Publishes a new version of Sissi) 2025-09-10 22:25:34 +00:00
release-bot
dd02b07ff6 [maven-release-plugin] prepare for next development iteration 2025-09-10 22:18:03 +00:00
90 changed files with 600 additions and 359 deletions

4
.env
View File

@@ -1,4 +1,4 @@
REGISTRY_PREFIX=harbor.sheldan.dev/sissi/ REGISTRY_PREFIX=harbor.sheldan.dev/sissi/
ABSTRACTO_PREFIX=harbor.sheldan.dev/abstracto/ ABSTRACTO_PREFIX=harbor.sheldan.dev/abstracto/
VERSION=1.5.11 VERSION=1.5.16
ABSTRACTO_VERSION=1.6.13 ABSTRACTO_VERSION=1.6.17

View File

@@ -3,7 +3,7 @@
<parent> <parent>
<groupId>dev.sheldan.sissi.application</groupId> <groupId>dev.sheldan.sissi.application</groupId>
<artifactId>application</artifactId> <artifactId>application</artifactId>
<version>1.5.12</version> <version>1.5.17-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<artifactId>executable</artifactId> <artifactId>executable</artifactId>

View File

@@ -3,7 +3,7 @@
<parent> <parent>
<groupId>dev.sheldan.sissi</groupId> <groupId>dev.sheldan.sissi</groupId>
<artifactId>sissi</artifactId> <artifactId>sissi</artifactId>
<version>1.5.12</version> <version>1.5.17-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
@@ -34,6 +34,11 @@
<artifactId>rssreader</artifactId> <artifactId>rssreader</artifactId>
<version>${rssreader.version}</version> <version>${rssreader.version}</version>
</dependency> </dependency>
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>${jsoup.version}</version>
</dependency>
</dependencies> </dependencies>
</dependencyManagement> </dependencyManagement>

View File

@@ -4,7 +4,7 @@
<parent> <parent>
<groupId>dev.sheldan.sissi.application.module.custom</groupId> <groupId>dev.sheldan.sissi.application.module.custom</groupId>
<artifactId>sissi-customizations</artifactId> <artifactId>sissi-customizations</artifactId>
<version>1.5.12</version> <version>1.5.17-SNAPSHOT</version>
</parent> </parent>
<artifactId>image-generation-custom</artifactId> <artifactId>image-generation-custom</artifactId>

View File

@@ -3,7 +3,7 @@
<parent> <parent>
<groupId>dev.sheldan.sissi.application.module.custom</groupId> <groupId>dev.sheldan.sissi.application.module.custom</groupId>
<artifactId>sissi-customizations</artifactId> <artifactId>sissi-customizations</artifactId>
<version>1.5.12</version> <version>1.5.17-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent> <parent>
<artifactId>application</artifactId> <artifactId>application</artifactId>
<groupId>dev.sheldan.sissi.application</groupId> <groupId>dev.sheldan.sissi.application</groupId>
<version>1.5.12</version> <version>1.5.17-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent> <parent>
<groupId>dev.sheldan.sissi.application</groupId> <groupId>dev.sheldan.sissi.application</groupId>
<artifactId>sissi-modules</artifactId> <artifactId>sissi-modules</artifactId>
<version>1.5.12</version> <version>1.5.17-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
@@ -15,6 +15,11 @@
<groupId>com.google.code.gson</groupId> <groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId> <artifactId>gson</artifactId>
</dependency> </dependency>
<dependency>
<groupId>dev.sheldan.abstracto.scheduling</groupId>
<artifactId>scheduling-int</artifactId>
<version>${abstracto.version}</version>
</dependency>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId> <artifactId>spring-boot-starter-web</artifactId>
@@ -28,6 +33,10 @@
<groupId>org.springframework</groupId> <groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId> <artifactId>spring-context-support</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
</dependency>
</dependencies> </dependencies>
<build> <build>

View File

@@ -7,10 +7,9 @@ import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import java.math.RoundingMode;
import java.util.List; import java.util.List;
import static dev.sheldan.sissi.module.debra.config.DebraFeatureConfig.DEBRA_DONATION_NOTIFICATION_SERVER_ID_ENV_NAME;
@RestController @RestController
@RequestMapping(value = "/debra") @RequestMapping(value = "/debra")
public class DebraDonationStatusController { public class DebraDonationStatusController {
@@ -20,50 +19,43 @@ public class DebraDonationStatusController {
@GetMapping(value = "/latestDonations", produces = "application/json") @GetMapping(value = "/latestDonations", produces = "application/json")
public DonationStats getLatestDonations() { public DonationStats getLatestDonations() {
Long serverId = Long.parseLong(System.getenv(DEBRA_DONATION_NOTIFICATION_SERVER_ID_ENV_NAME)); DonationsResponse donationResponse = donationService.getSynchronizedCachedDonationAmount();
DonationsResponse donationResponse = donationService.getSynchronizedCachedDonationAmount(serverId);
List<DonationInfo> donations = donationService.getLatestDonations(donationResponse, Integer.MAX_VALUE) List<DonationInfo> donations = donationService.getLatestDonations(donationResponse, Integer.MAX_VALUE)
.stream() .stream()
.map(DonationInfo::fromDonationItemModel) .map(DonationInfo::fromDonationItemModel)
.toList(); .toList();
return DonationStats return DonationStats
.builder() .builder()
.totalAmount(donationResponse.getPage().getCollected()) .totalAmount(donationResponse.getCurrentDonationAmount())
.donations(donations) .donations(donations)
.build(); .build();
} }
@GetMapping(value = "/highestDonations", produces = "application/json") @GetMapping(value = "/highestDonations", produces = "application/json")
public DonationStats getHighestDonations() { public DonationStats getHighestDonations() {
Long serverId = Long.parseLong(System.getenv(DEBRA_DONATION_NOTIFICATION_SERVER_ID_ENV_NAME)); DonationsResponse donationResponse = donationService.getSynchronizedCachedDonationAmount();
DonationsResponse donationResponse = donationService.getSynchronizedCachedDonationAmount(serverId);
List<DonationInfo> donations = donationService.getHighestDonations(donationResponse, Integer.MAX_VALUE) List<DonationInfo> donations = donationService.getHighestDonations(donationResponse, Integer.MAX_VALUE)
.stream() .stream()
.map(DonationInfo::fromDonationItemModel) .map(DonationInfo::fromDonationItemModel)
.toList(); .toList();
return DonationStats return DonationStats
.builder() .builder()
.totalAmount(donationResponse.getPage().getCollected()) .totalAmount(donationResponse.getCurrentDonationAmount())
.donations(donations) .donations(donations)
.build(); .build();
} }
@GetMapping(value = "/campaignInfo", produces = "application/json") @GetMapping(value = "/campaignInfo", produces = "application/json")
public CampaignInfo getCampaignInfo() { public CampaignInfo getCampaignInfo() {
Long serverId = Long.parseLong(System.getenv(DEBRA_DONATION_NOTIFICATION_SERVER_ID_ENV_NAME)); DonationsResponse donationResponse = donationService.getSynchronizedCachedDonationAmount();
DonationsResponse donationResponse = donationService.getSynchronizedCachedDonationAmount(serverId);
Description pageObject = donationResponse.getPage();
return CampaignInfo return CampaignInfo
.builder() .builder()
.collected(pageObject.getCollected())
.collectedNet(pageObject.getCollectedNet())
.donationCount(donationResponse.getDonationCount()) .donationCount(donationResponse.getDonationCount())
.currency(pageObject.getCurrency()) .collected(donationResponse.getCurrentDonationAmount())
.percent(pageObject.getPercent()) .target(donationResponse.getDonationAmountGoal())
.displayName(pageObject.getDisplayName()) .percent(donationResponse.getCurrentDonationAmount().divide(donationResponse.getDonationAmountGoal(), RoundingMode.CEILING))
.slug(pageObject.getSlug()) .currency("")
.target(pageObject.getTarget())
.build(); .build();
} }
} }

View File

@@ -36,8 +36,8 @@ public class EndlessStreamController {
public EndlessStreamInfo getLatestDonations(@PathVariable("id") Long id) { public EndlessStreamInfo getLatestDonations(@PathVariable("id") Long id) {
Long serverId = Long.parseLong(System.getenv(DEBRA_DONATION_NOTIFICATION_SERVER_ID_ENV_NAME)); Long serverId = Long.parseLong(System.getenv(DEBRA_DONATION_NOTIFICATION_SERVER_ID_ENV_NAME));
EndlessStream endlessStream = endlessStreamManagementServiceBean.getEndlessStream(id); EndlessStream endlessStream = endlessStreamManagementServiceBean.getEndlessStream(id);
DonationsResponse donationInfo = donationService.getSynchronizedCachedDonationAmount(serverId); DonationsResponse donationInfo = donationService.getSynchronizedCachedDonationAmount();
BigDecimal collectedAmount = donationInfo.getPage().getCollected(); BigDecimal collectedAmount = donationInfo.getCurrentDonationAmount();
Long minuteRate = configService.getLongValueOrConfigDefault(DebraFeatureConfig.ENDLESS_STREAM_MINUTE_RATE, serverId); Long minuteRate = configService.getLongValueOrConfigDefault(DebraFeatureConfig.ENDLESS_STREAM_MINUTE_RATE, serverId);
Instant endDate = endlessStream.getStartTime().plus(collectedAmount.multiply(new BigDecimal(minuteRate)).toBigInteger().longValue(), ChronoUnit.MINUTES); Instant endDate = endlessStream.getStartTime().plus(collectedAmount.multiply(new BigDecimal(minuteRate)).toBigInteger().longValue(), ChronoUnit.MINUTES);
return EndlessStreamInfo return EndlessStreamInfo

View File

@@ -6,9 +6,9 @@ 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.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.CommandParameterKey;
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.interaction.slash.parameter.SlashCommandParameterService;
@@ -26,7 +26,6 @@ import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEve
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.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
@@ -70,11 +69,12 @@ public class Donations extends AbstractConditionableCommand {
Integer selectionValue = (Integer) parameters.get(1); Integer selectionValue = (Integer) parameters.get(1);
Integer top = null; Integer top = null;
Integer latest = null; Integer latest = null;
switch (type) { if(type != null) {
case "top": top = selectionValue; break; DonationsTypeParameterKey typeKey = CommandParameterKey.getEnumFromKey(DonationsTypeParameterKey.class, type);
default: switch (typeKey) {
case "latest" : case LATEST -> latest = selectionValue;
latest = selectionValue; break; case TOP -> top = selectionValue;
}
} }
messageToSend = getDonationMessageToSend(commandContext.getGuild().getIdLong(), top, latest); messageToSend = getDonationMessageToSend(commandContext.getGuild().getIdLong(), top, latest);
} }
@@ -98,11 +98,10 @@ public class Donations extends AbstractConditionableCommand {
Integer top = null; Integer top = null;
Integer latest = null; Integer latest = null;
if(selectionType != null) { if(selectionType != null) {
switch (selectionType) { DonationsTypeParameterKey typeKey = CommandParameterKey.getEnumFromKey(DonationsTypeParameterKey.class, selectionType);
case "top": top = selectionValue; break; switch (typeKey) {
default: case LATEST -> latest = selectionValue;
case "latest" : case TOP -> top = selectionValue;
latest = selectionValue; break;
} }
} }
@@ -113,7 +112,7 @@ public class Donations extends AbstractConditionableCommand {
private MessageToSend getDonationMessageToSend(Long serverId, Integer top, Integer latest) { private MessageToSend getDonationMessageToSend(Long serverId, Integer top, Integer latest) {
DonationsModel donationModel; DonationsModel donationModel;
DonationsResponse donationResponse = donationService.fetchCurrentDonationAmount(serverId); DonationsResponse donationResponse = donationService.fetchCurrentDonations();
donationModel = donationConverter.convertDonationResponse(donationResponse); donationModel = donationConverter.convertDonationResponse(donationResponse);
if(top != null) { if(top != null) {
donationModel.setDonations(donationService.getHighestDonations(donationResponse, top)); donationModel.setDonations(donationService.getHighestDonations(donationResponse, top));
@@ -146,7 +145,7 @@ public class Donations extends AbstractConditionableCommand {
.templated(true) .templated(true)
.name(SELECTION_PARAMETER) .name(SELECTION_PARAMETER)
.optional(true) .optional(true)
.type(String.class) .type(DonationsTypeParameterKey.class)
.build(); .build();

View File

@@ -0,0 +1,13 @@
package dev.sheldan.sissi.module.debra.commands;
import dev.sheldan.abstracto.core.command.execution.CommandParameterKey;
import lombok.AllArgsConstructor;
import lombok.Getter;
@Getter
@AllArgsConstructor
public enum DonationsTypeParameterKey implements CommandParameterKey {
TOP("top"), LATEST("latest");
private String key;
}

View File

@@ -13,7 +13,6 @@ 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 ENDLESS_STREAM_MINUTE_RATE = "endlessStreamMinuteRate"; public static final String ENDLESS_STREAM_MINUTE_RATE = "endlessStreamMinuteRate";
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() {
@@ -27,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, DEBRA_DONATION_API_FETCH_SIZE_KEY, ENDLESS_STREAM_MINUTE_RATE); return Arrays.asList(DEBRA_DONATION_NOTIFICATION_DELAY_CONFIG_KEY, ENDLESS_STREAM_MINUTE_RATE);
} }
} }

View File

@@ -10,6 +10,5 @@ import org.springframework.context.annotation.Configuration;
@Setter @Setter
@ConfigurationProperties(prefix = "sissi.debra") @ConfigurationProperties(prefix = "sissi.debra")
public class DebraProperties { public class DebraProperties {
private String websocketURL; private String donationPageUrl;
private String donationAPIUrl;
} }

View File

@@ -1,6 +1,6 @@
package dev.sheldan.sissi.module.debra.converter; package dev.sheldan.sissi.module.debra.converter;
import dev.sheldan.sissi.module.debra.model.api.Donation; import dev.sheldan.sissi.module.debra.model.api.DonationDto;
import dev.sheldan.sissi.module.debra.model.api.DonationsResponse; 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.DonationItemModel;
import dev.sheldan.sissi.module.debra.model.commands.DonationsModel; import dev.sheldan.sissi.module.debra.model.commands.DonationsModel;
@@ -9,20 +9,19 @@ import org.springframework.stereotype.Component;
@Component @Component
public class DonationConverter { public class DonationConverter {
public DonationItemModel convertDonation(Donation donation) { public DonationItemModel convertDonation(DonationDto donation) {
return DonationItemModel return DonationItemModel
.builder() .builder()
.donationAmount(donation.getAmount()) .donationAmount(donation.getAmount())
.firstName(donation.getFirstname()) .name(donation.getName())
.lastName(donation.getLastname()) .anonymous(BooleanUtils.toBoolean(donation.getAnonymous()))
.anonymous(BooleanUtils.toBoolean(donation.getAnonym()))
.build(); .build();
} }
public DonationsModel convertDonationResponse(DonationsResponse response) { public DonationsModel convertDonationResponse(DonationsResponse response) {
return DonationsModel return DonationsModel
.builder() .builder()
.totalAmount(response.getPage().getCollected()) .totalAmount(response.getCurrentDonationAmount())
.build(); .build();
} }
} }

View File

@@ -0,0 +1,31 @@
package dev.sheldan.sissi.module.debra.job;
import dev.sheldan.sissi.module.debra.service.DonationService;
import lombok.extern.slf4j.Slf4j;
import org.quartz.DisallowConcurrentExecution;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.PersistJobDataAfterExecution;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.quartz.QuartzJobBean;
import org.springframework.stereotype.Component;
@Slf4j
@DisallowConcurrentExecution
@Component
@PersistJobDataAfterExecution
public class DonationFetchJob extends QuartzJobBean {
@Autowired
private DonationService donationService;
@Override
protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
try {
log.info("Checking for new donations.");
donationService.checkForNewDonations();
} catch (Exception e) {
log.error("Failed to check for new donations.", e);
}
}
}

View File

@@ -1,96 +0,0 @@
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.listener.DonationResponseModel;
import dev.sheldan.sissi.module.debra.service.DonationService;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.Nullable;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import static dev.sheldan.sissi.module.debra.config.DebraFeatureConfig.DEBRA_DONATION_NOTIFICATION_DELAY_CONFIG_KEY;
import static dev.sheldan.sissi.module.debra.config.DebraFeatureConfig.DEBRA_DONATION_NOTIFICATION_SERVER_ID_ENV_NAME;
@Component
@Slf4j
public class WebsocketListener extends WebSocketListener implements AsyncStartupListener {
@Autowired
private DonationService donationService;
@Autowired
private DebraProperties debraProperties;
@Autowired
private ConfigService configService;
private WebSocket webSocketObj;
private OkHttpClient clientObj;
@Override
public void onOpen(WebSocket webSocket, Response response) {
log.info("Connected to donation websocket.");
super.onOpen(webSocket, response);
}
@Override
public void onMessage(WebSocket webSocket, String text) {
CompletableFuture.runAsync(() -> {
log.info("Handling received message on websocket.");
try {
Long targetServerId = Long.parseLong(System.getenv(DEBRA_DONATION_NOTIFICATION_SERVER_ID_ENV_NAME));
Long delayMillis = configService.getLongValueOrConfigDefault(DEBRA_DONATION_NOTIFICATION_DELAY_CONFIG_KEY, targetServerId);
log.info("Waiting {} milli seconds to send notification.", delayMillis);
Thread.sleep(delayMillis);
log.info("Loading new donation amount and sending notification.");
DonationResponseModel donation = donationService.parseDonationFromMessage(text);
donationService.sendDonationNotification(donation).thenAccept(unused -> {
log.info("Successfully notified about donation.");
}).exceptionally(throwable -> {
log.error("Failed to notify about donation.", throwable);
return null;
});
} catch (Exception exception) {
log.error("Failed to handle websocket message.", exception);
}
});
}
@Override
public void onFailure(WebSocket webSocket, Throwable t, @Nullable Response response) {
log.warn("Websocket connection failed...", t);
}
@Override
public void onClosing(WebSocket webSocket, int code, String reason) {
log.info("Closing websocket connection. It was closed with code {} and reason {}.", code, reason);
}
@Override
public void execute() {
if(clientObj != null) {
clientObj.connectionPool().evictAll();
clientObj.dispatcher().executorService().shutdownNow();
}
clientObj = new OkHttpClient.Builder()
.readTimeout(0, TimeUnit.MILLISECONDS)
.retryOnConnectionFailure(true)
.build();
startConnection(clientObj);
clientObj.dispatcher().executorService().shutdown();
}
private void startConnection(OkHttpClient client) {
log.info("Starting websocket connection.");
Request request = new Request.Builder()
.url(debraProperties.getWebsocketURL())
.build();
this.webSocketObj = client.newWebSocket(request, this);
}
}

View File

@@ -4,17 +4,13 @@ import lombok.Builder;
import lombok.Getter; import lombok.Getter;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.math.BigInteger;
@Builder @Builder
@Getter @Getter
public class CampaignInfo { public class CampaignInfo {
private BigInteger donationCount; private Integer donationCount;
private BigDecimal collected; private BigDecimal collected;
private BigDecimal target; private BigDecimal target;
private String currency; private String currency;
private String slug;
private String displayName;
private BigDecimal collectedNet;
private BigDecimal percent; private BigDecimal percent;
} }

View File

@@ -1,28 +0,0 @@
package dev.sheldan.sissi.module.debra.model.api;
import com.google.gson.annotations.SerializedName;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
import java.math.BigDecimal;
@Getter
@Setter
@Builder
public class Description {
@SerializedName("collected")
private BigDecimal collected;
@SerializedName("target")
private BigDecimal target;
@SerializedName("currency")
private String currency;
@SerializedName("slug")
private String slug;
@SerializedName("displayname")
private String displayName;
@SerializedName("collectednet")
private BigDecimal collectedNet;
@SerializedName("percent")
private BigDecimal percent;
}

View File

@@ -1,26 +0,0 @@
package dev.sheldan.sissi.module.debra.model.api;
import com.google.gson.annotations.SerializedName;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
import java.math.BigDecimal;
@Getter
@Setter
@Builder
public class Donation {
@SerializedName("amount")
private BigDecimal amount;
@SerializedName("currency")
private String currency;
@SerializedName("text")
private String text;
@SerializedName("anonym")
private Integer anonym;
@SerializedName("firstname")
private String firstname;
@SerializedName("lastname")
private String lastname;
}

View File

@@ -0,0 +1,27 @@
package dev.sheldan.sissi.module.debra.model.api;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
@Getter
@Setter
@Builder
@ToString
public class DonationDto {
private BigDecimal amount;
private String currency;
private String text;
private Boolean anonymous;
private String name;
private LocalDate date;
public String stringRepresentation() {
return String.format("%s %s %s %s %s", name, amount, text, anonymous, date.format(DateTimeFormatter.ISO_DATE));
}
}

View File

@@ -11,7 +11,7 @@ import java.math.BigDecimal;
@Setter @Setter
@Builder @Builder
public class DonationInfo { public class DonationInfo {
private String firstName; private String name;
private BigDecimal donationAmount; private BigDecimal donationAmount;
private Boolean anonymous; private Boolean anonymous;
@@ -20,7 +20,7 @@ public class DonationInfo {
.builder() .builder()
.donationAmount(donationItemModel.getDonationAmount()) .donationAmount(donationItemModel.getDonationAmount())
.anonymous(donationItemModel.getAnonymous()) .anonymous(donationItemModel.getAnonymous())
.firstName(donationItemModel.getFirstName()) .name(donationItemModel.getName())
.build(); .build();
} }
} }

View File

@@ -1,21 +1,18 @@
package dev.sheldan.sissi.module.debra.model.api; package dev.sheldan.sissi.module.debra.model.api;
import com.google.gson.annotations.SerializedName;
import lombok.Builder; import lombok.Builder;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import java.math.BigInteger; import java.math.BigDecimal;
import java.util.List; import java.util.List;
@Getter @Getter
@Setter @Setter
@Builder @Builder
public class DonationsResponse { public class DonationsResponse {
@SerializedName("page") private BigDecimal currentDonationAmount;
private Description page; private BigDecimal donationAmountGoal;
@SerializedName("donation_count") private int donationCount;
private BigInteger donationCount; private List<DonationDto> donations;
@SerializedName("donations")
private List<Donation> donations;
} }

View File

@@ -5,13 +5,14 @@ import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.time.LocalDate;
@Getter @Getter
@Setter @Setter
@Builder @Builder
public class DonationItemModel { public class DonationItemModel {
private String firstName; private String name;
private String lastName; private LocalDate date;
private BigDecimal donationAmount; private BigDecimal donationAmount;
private Boolean anonymous; private Boolean anonymous;
} }

View File

@@ -0,0 +1,30 @@
package dev.sheldan.sissi.module.debra.model.database;
import jakarta.persistence.*;
import lombok.*;
import java.time.Instant;
@Builder
@Entity
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "donation")
@Getter
@Setter
@EqualsAndHashCode
public class Donation {
@Id
@Column(name = "id", nullable = false)
private String id;
// we cant be sure about duplicates
@Column(name = "count")
private Integer count;
@Column(name = "created")
private Instant created;
@Column(name = "updated")
private Instant updated;
}

View File

@@ -11,6 +11,7 @@ import java.math.BigDecimal;
@ToString @ToString
public class DonationResponseModel { public class DonationResponseModel {
private String donatorName; private String donatorName;
private Boolean anonymous;
private BigDecimal amount; private BigDecimal amount;
private String message; private String message;
} }

View File

@@ -0,0 +1,9 @@
package dev.sheldan.sissi.module.debra.repository;
import dev.sheldan.sissi.module.debra.model.database.Donation;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface DonationRepository extends JpaRepository<Donation, String> {
}

View File

@@ -1,52 +1,52 @@
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.exception.AbstractoRunTimeException; import dev.sheldan.abstracto.core.exception.AbstractoRunTimeException;
import dev.sheldan.abstracto.core.interaction.ComponentPayloadService; import dev.sheldan.abstracto.core.interaction.ComponentPayloadService;
import dev.sheldan.abstracto.core.interaction.ComponentService; import dev.sheldan.abstracto.core.interaction.ComponentService;
import dev.sheldan.abstracto.core.models.database.AServer; import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.core.service.ChannelService; import dev.sheldan.abstracto.core.service.ChannelService;
import dev.sheldan.abstracto.core.service.ConfigService; import dev.sheldan.abstracto.core.service.HashService;
import dev.sheldan.abstracto.core.service.PostTargetService; import dev.sheldan.abstracto.core.service.PostTargetService;
import dev.sheldan.abstracto.core.service.management.ServerManagementService; import dev.sheldan.abstracto.core.service.management.ServerManagementService;
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.CompletableFutureList;
import dev.sheldan.abstracto.core.utils.FutureUtils; import dev.sheldan.abstracto.core.utils.FutureUtils;
import dev.sheldan.sissi.module.debra.exception.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.converter.DonationConverter; 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.DonationDto;
import dev.sheldan.sissi.module.debra.model.api.DonationsResponse; import dev.sheldan.sissi.module.debra.model.api.DonationsResponse;
import dev.sheldan.sissi.module.debra.model.commands.DebraInfoButtonPayload; import dev.sheldan.sissi.module.debra.model.commands.DebraInfoButtonPayload;
import dev.sheldan.sissi.module.debra.model.commands.DebraInfoModel; import dev.sheldan.sissi.module.debra.model.commands.DebraInfoModel;
import dev.sheldan.sissi.module.debra.model.commands.DonationItemModel; 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.commands.DonationsModel;
import dev.sheldan.sissi.module.debra.model.database.Donation;
import dev.sheldan.sissi.module.debra.model.listener.DonationResponseModel; 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 dev.sheldan.sissi.module.debra.service.management.DonationManagementServiceBean;
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 net.dv8tion.jda.api.entities.channel.middleman.GuildMessageChannel; import net.dv8tion.jda.api.entities.channel.middleman.GuildMessageChannel;
import okhttp3.OkHttpClient; import org.apache.commons.lang3.tuple.Pair;
import okhttp3.Request; import org.jsoup.Jsoup;
import okhttp3.Response; import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable; import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import java.io.IOException;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.Comparator; import java.text.DecimalFormat;
import java.util.List; import java.text.DecimalFormatSymbols;
import java.util.Optional; import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors; 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
@@ -62,15 +62,9 @@ public class DonationService {
@Autowired @Autowired
private TemplateService templateService; private TemplateService templateService;
@Autowired
private OkHttpClient okHttpClient;
@Autowired @Autowired
private DonationConverter donationConverter; private DonationConverter donationConverter;
@Autowired
private ConfigService configService;
@Autowired @Autowired
private ChannelService channelService; private ChannelService channelService;
@@ -83,100 +77,209 @@ public class DonationService {
@Autowired @Autowired
private ServerManagementService serverManagementService; private ServerManagementService serverManagementService;
@Autowired
private DonationManagementServiceBean donationManagementServiceBean;
@Autowired
private HashService hashService;
@Autowired @Autowired
private DonationService self; private DonationService self;
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 String DEBRA_INFO_BUTTON_MESSAGE_TEMPLATE_KEY = "debraInfoButton"; private static final String DEBRA_INFO_BUTTON_MESSAGE_TEMPLATE_KEY = "debraInfoButton";
public static final String DEBRA_INFO_BUTTON_ORIGIN = "DEBRA_INFO_BUTTON"; public static final String DEBRA_INFO_BUTTON_ORIGIN = "DEBRA_INFO_BUTTON";
private static final DateTimeFormatter DATE_FORMAT = DateTimeFormatter.ofPattern("d.M.y");
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("(<br>)+", " ")).map(String::trim).orElse("");
return DonationResponseModel
.builder()
.message(donationMessage)
.donatorName(donatorName)
.amount(amount)
.build();
} else {
throw new IllegalArgumentException("String in wrong format");
}
}
public List<DonationItemModel> getHighestDonations(DonationsResponse response, Integer maxCount) { public List<DonationItemModel> getHighestDonations(DonationsResponse response, Integer maxCount) {
List<Donation> topDonations = response return response
.getDonations() .getDonations()
.stream() .stream()
.sorted(Comparator.comparing(Donation::getAmount) .sorted(Comparator.comparing(DonationDto::getAmount)
.reversed()) .reversed())
.collect(Collectors.toList());
return topDonations
.stream()
.limit(maxCount) .limit(maxCount)
.map(donation -> donationConverter.convertDonation(donation)) .map(donation -> donationConverter.convertDonation(donation))
.collect(Collectors.toList()); .toList();
} }
public List<DonationItemModel> getLatestDonations(DonationsResponse response, Integer maxCount) { public List<DonationItemModel> getLatestDonations(DonationsResponse response, Integer maxCount) {
return response return response
.getDonations() .getDonations()
.stream() .stream()
.sorted(Comparator.comparing(DonationDto::getDate).reversed())
.limit(maxCount) .limit(maxCount)
.map(donation -> donationConverter.convertDonation(donation)) .map(donation -> donationConverter.convertDonation(donation))
.collect(Collectors.toList()); .collect(Collectors.toList());
} }
public synchronized DonationsResponse getSynchronizedCachedDonationAmount(Long serverId) { public synchronized DonationsResponse getSynchronizedCachedDonationAmount() {
return self.getCachedDonationAmount(serverId); return self.getCachedDonationAmount();
} }
@Cacheable(value = "donation-cache") @Cacheable(value = "donation-cache")
public synchronized DonationsResponse getCachedDonationAmount(Long serverId) { public synchronized DonationsResponse getCachedDonationAmount() {
return self.fetchCurrentDonationAmount(serverId); return self.fetchCurrentDonations();
} }
public DonationsResponse fetchCurrentDonationAmount(Long serverId) { public DonationsResponse fetchCurrentDonations() {
try { try {
Long fetchSize = configService.getLongValueOrConfigDefault(DEBRA_DONATION_API_FETCH_SIZE_KEY, serverId); Document donationPage = Jsoup.connect(debraProperties.getDonationPageUrl()).get();
Request request = new Request.Builder() DecimalFormat decimalFormat = getDecimalFormat();
.url(String.format(debraProperties.getDonationAPIUrl(), fetchSize)) Element endValueElement = donationPage.getElementById("end-value");
.get() String endValueString = endValueElement.text();
.build(); Elements currentValueElement = donationPage.getElementsByClass("current_amount").get(0).getElementsByClass("value");
Response response = okHttpClient.newCall(request).execute(); String[] valueArray = currentValueElement.text().split(" ");
if(!response.isSuccessful()) { String currentValueString = valueArray[0];
log.error("Failed to retrieve donation response. Response had code {} with body {} and headers {}.", String currency = valueArray[1];
response.code(), response.body().string(), response.headers()); BigDecimal currentValue = (BigDecimal) decimalFormat.parse(currentValueString);
throw new DonationAmountNotFoundException(); BigDecimal endValue = (BigDecimal) decimalFormat.parse(endValueString);
Element list = donationPage.getElementsByClass("donor-list").first();
Elements donationElements = list.getElementsByClass("list-item");
List<DonationDto> donations = new ArrayList<>();
for (Element donationMainElement : donationElements.asList()) {
Elements nameElement = donationMainElement.getElementsByClass("donor-list-name");
Elements dateElement = donationMainElement.getElementsByClass("donor-list-date");
Elements amountElement = donationMainElement.getElementsByClass("donor-list-amount");
Elements textElement = donationMainElement.getElementsByClass("donor-list-amount-text");
LocalDate dateValue;
if (dateElement.hasText()) {
dateValue = LocalDate.parse(dateElement.text(), DATE_FORMAT);
} else {
dateValue = null;
}
BigDecimal amount;
if (amountElement.hasText()) {
String amountText = amountElement.text().split(" ")[0];
amount = (BigDecimal) decimalFormat.parse(amountText);
} else {
amount = null;
}
String additionalText = textElement.text();
String name = nameElement.text();
boolean anonymous = name.isBlank();
donations.add(DonationDto
.builder()
.anonymous(anonymous)
.name(nameElement.text())
.amount(amount)
.currency(currency)
.name(name)
.text(additionalText)
.date(dateValue)
.build());
} }
Gson gson = getGson(); return DonationsResponse
return gson.fromJson(response.body().string(), DonationsResponse.class); .builder()
.donations(donations)
.currentDonationAmount(currentValue)
.donationAmountGoal(endValue)
.donationCount(donations.size())
.build();
} catch (Exception exception) { } catch (Exception exception) {
throw new AbstractoRunTimeException(exception); throw new AbstractoRunTimeException(exception);
} }
} }
private Gson getGson() { private DecimalFormat getDecimalFormat() {
return new GsonBuilder() DecimalFormatSymbols symbols = new DecimalFormatSymbols();
.registerTypeAdapter(BigDecimal.class, new BigDecimalGsonAdapter()) symbols.setGroupingSeparator('.');
.create(); symbols.setDecimalSeparator(',');
String pattern = "#,##0.0#";
DecimalFormat decimalFormat = new DecimalFormat(pattern, symbols);
decimalFormat.setParseBigDecimal(true);
return decimalFormat;
} }
private DonationsModel getDonationInfoModel(Long serverId) { private DonationsModel getDonationInfoModel() {
return donationConverter.convertDonationResponse(fetchCurrentDonationAmount(serverId)); return donationConverter.convertDonationResponse(fetchCurrentDonations());
} }
public CompletableFuture<Void> sendDonationNotification(DonationResponseModel donation) throws IOException {
private String hashDonation(DonationDto donation) {
return hashService.sha256HashString(donation.stringRepresentation());
}
@Transactional
public void checkForNewDonations() {
List<Donation> allDonations = donationManagementServiceBean.getAllDonations();
Map<String, Integer> existingHashes = allDonations
.stream()
.collect(Collectors.toMap(Donation::getId, Donation::getCount));
DonationsResponse donationResponse = fetchCurrentDonations();
Map<String, Pair<Integer, DonationDto>> donationFromPageHashes = new HashMap<>();
donationResponse.getDonations().forEach(donationDto -> {
String thisHash = hashDonation(donationDto);
if(donationFromPageHashes.containsKey(thisHash)) {
donationFromPageHashes.put(thisHash, Pair.of(donationFromPageHashes.get(thisHash).getLeft() + 1, donationDto));
} else {
donationFromPageHashes.put(thisHash, Pair.of(1, donationDto));
}
});
Set<String> pageHashesToRemove = new HashSet<>();
donationFromPageHashes.entrySet().forEach(pageHash -> {
if(existingHashes.containsKey(pageHash.getKey())) {
Integer existingDonation = existingHashes.get(pageHash.getKey());
int amountDifference = pageHash.getValue().getKey() - existingDonation;
if(amountDifference == 0) {
pageHashesToRemove.add(pageHash.getKey()); // it matches 1:1, we know about all of them already
} if(amountDifference < 0) {
pageHashesToRemove.add(pageHash.getKey());
log.warn("We have more donations than on the page of hash {}:{}.", pageHash.getKey(), amountDifference);
} else {
pageHash.setValue(Pair.of(amountDifference, pageHash.getValue().getRight()));
}
}
});
pageHashesToRemove.forEach(donationFromPageHashes::remove);
if(donationFromPageHashes.isEmpty()) {
log.info("No new donations - ending search.");
return;
}
List<CompletableFuture<Void>> notificationFutures = new ArrayList<>();
donationFromPageHashes.values().forEach(donationInfo -> {
for (int i = 0; i < donationInfo.getLeft(); i++) {
DonationDto donationDto = donationInfo.getRight();
DonationResponseModel model = DonationResponseModel
.builder()
.message(donationDto.getText())
.donatorName(donationDto.getName())
.amount(donationDto.getAmount())
.anonymous(donationDto.getAnonymous())
.build();
notificationFutures.add(sendDonationNotification(model));
}
});
new CompletableFutureList<>(notificationFutures).getMainFuture().thenAccept(unused -> {
log.info("All {} notifications send.", notificationFutures.size());
}).exceptionally(throwable -> {
log.warn("Failed to send notifications about {} new donations.", notificationFutures.size(), throwable);
return null;
});
log.info("Creating/updating {} donation entries.", donationFromPageHashes.size());
allDonations.forEach(donation -> {
Set<String> donationsToRemoveBecauseUpdate = new HashSet<>();
donationFromPageHashes.forEach((key, value) -> {
// its assumed that donationFromPageHashes only contains donations that need to be created
if (donation.getId().equals(key)) {
donation.setCount(value.getLeft() + donation.getCount());
donationManagementServiceBean.updateDonation(donation);
donationsToRemoveBecauseUpdate.add(key);
}
});
donationsToRemoveBecauseUpdate.forEach(donationFromPageHashes::remove);
});
donationFromPageHashes.forEach((key, value) ->
donationManagementServiceBean.saveDonation(key, value.getLeft()));
}
public CompletableFuture<Void> sendDonationNotification(DonationResponseModel donation) {
Long targetServerId = Long.parseLong(System.getenv(DEBRA_DONATION_NOTIFICATION_SERVER_ID_ENV_NAME)); Long targetServerId = Long.parseLong(System.getenv(DEBRA_DONATION_NOTIFICATION_SERVER_ID_ENV_NAME));
DonationsModel donationInfoModel = getDonationInfoModel(targetServerId); DonationsModel donationInfoModel = getDonationInfoModel();
DonationNotificationModel model = DonationNotificationModel DonationNotificationModel model = DonationNotificationModel
.builder() .builder()
.donation(donation) .donation(donation)

View File

@@ -0,0 +1,33 @@
package dev.sheldan.sissi.module.debra.service.management;
import dev.sheldan.sissi.module.debra.model.database.Donation;
import dev.sheldan.sissi.module.debra.repository.DonationRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.List;
@Component
public class DonationManagementServiceBean {
@Autowired
private DonationRepository donationRepository;
public List<Donation> getAllDonations() {
return donationRepository.findAll();
}
public void updateDonation(Donation donation) {
donationRepository.save(donation);
}
public Donation saveDonation(String hash, Integer count) {
Donation donation = Donation
.builder()
.id(hash)
.count(count)
.build();
return donationRepository.save(donation);
}
}

View File

@@ -4,8 +4,7 @@ abstracto.featureFlags.debra.enabled=false
abstracto.postTargets.debraDonationNotification.name=debraDonationNotification 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.donationPageUrl=https://secure.sicherhelfen.org/campaigns/07a3baf6-5cdc-4300-854b-ea2b36b0b218/show
sissi.debra.donationAPIUrl=https://www.altruja.de/api/page/discord-schmetterlingsaktion-2024?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

View File

@@ -0,0 +1,7 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog https://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.26.xsd" >
<include file="seedData/data.xml" relativeToChangelogFile="true"/>
<include file="tables/tables.xml" relativeToChangelogFile="true"/>
</databaseChangeLog>

View File

@@ -0,0 +1,6 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog https://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.26.xsd" >
<include file="donation_fetch_job.xml" relativeToChangelogFile="true"/>
</databaseChangeLog>

View File

@@ -0,0 +1,15 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog https://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.26.xsd" >
<changeSet author="Sheldan" id="donation_fetch_job-insert">
<insert tableName="scheduler_job">
<column name="name" value="donationFetchJob"/>
<column name="group_name" value="debra"/>
<column name="clazz" value="dev.sheldan.sissi.module.debra.job.DonationFetchJob"/>
<column name="active" value="true"/>
<column name="cron_expression" value="0 */2 * * * ?"/>
<column name="recovery" value="false"/>
</insert>
</changeSet>
</databaseChangeLog>

View File

@@ -0,0 +1,28 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog https://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.26.xsd" >
<changeSet author="Sheldan" id="donation-table">
<createTable tableName="donation">
<column name="id" type="TEXT">
<constraints nullable="false"/>
</column>
<column name="count" type="NUMERIC">
<constraints nullable="false"/>
</column>
<column name="created" type="TIMESTAMP WITHOUT TIME ZONE">
<constraints nullable="false"/>
</column>
<column name="updated" type="TIMESTAMP WITHOUT TIME ZONE"/>
</createTable>
<sql>
DROP TRIGGER IF EXISTS donation_update_trigger ON donation;
CREATE TRIGGER donation_update_trigger BEFORE UPDATE ON donation FOR EACH ROW EXECUTE PROCEDURE update_trigger_procedure();
</sql>
<sql>
DROP TRIGGER IF EXISTS donation_insert_trigger ON donation;
CREATE TRIGGER donation_insert_trigger BEFORE INSERT ON donation FOR EACH ROW EXECUTE PROCEDURE insert_trigger_procedure();
</sql>
</changeSet>
</databaseChangeLog>

View File

@@ -0,0 +1,6 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog https://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.26.xsd" >
<include file="donation.xml" relativeToChangelogFile="true"/>
</databaseChangeLog>

View File

@@ -5,4 +5,5 @@
<include file="1.3.6/collection.xml" relativeToChangelogFile="true"/> <include file="1.3.6/collection.xml" relativeToChangelogFile="true"/>
<include file="1.4.21/collection.xml" relativeToChangelogFile="true"/> <include file="1.4.21/collection.xml" relativeToChangelogFile="true"/>
<include file="1.4.29/collection.xml" relativeToChangelogFile="true"/> <include file="1.4.29/collection.xml" relativeToChangelogFile="true"/>
<include file="1.5.16/collection.xml" relativeToChangelogFile="true"/>
</databaseChangeLog> </databaseChangeLog>

View File

@@ -3,7 +3,7 @@
<parent> <parent>
<groupId>dev.sheldan.sissi.application</groupId> <groupId>dev.sheldan.sissi.application</groupId>
<artifactId>sissi-modules</artifactId> <artifactId>sissi-modules</artifactId>
<version>1.5.12</version> <version>1.5.17-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent> <parent>
<artifactId>sissi-modules</artifactId> <artifactId>sissi-modules</artifactId>
<groupId>dev.sheldan.sissi.application</groupId> <groupId>dev.sheldan.sissi.application</groupId>
<version>1.5.12</version> <version>1.5.17-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent> <parent>
<groupId>dev.sheldan.sissi.application</groupId> <groupId>dev.sheldan.sissi.application</groupId>
<artifactId>application</artifactId> <artifactId>application</artifactId>
<version>1.5.12</version> <version>1.5.17-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent> <parent>
<groupId>dev.sheldan.sissi.application</groupId> <groupId>dev.sheldan.sissi.application</groupId>
<artifactId>sissi-modules</artifactId> <artifactId>sissi-modules</artifactId>
<version>1.5.12</version> <version>1.5.17-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent> <parent>
<artifactId>sissi-modules</artifactId> <artifactId>sissi-modules</artifactId>
<groupId>dev.sheldan.sissi.application</groupId> <groupId>dev.sheldan.sissi.application</groupId>
<version>1.5.12</version> <version>1.5.17-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -2,4 +2,4 @@ apiVersion: v2
name: sissi name: sissi
description: A Helm chart for Kubernetes description: A Helm chart for Kubernetes
type: application type: application
version: 1.5.11 version: 1.5.16

View File

@@ -60,7 +60,7 @@ spec:
- name: DB_SCHEMA - name: DB_SCHEMA
value: {{ .Values.dbCredentials.schema }} value: {{ .Values.dbCredentials.schema }}
- name: DEBRA_DONATION_NOTIFICATION_SERVER_ID - name: DEBRA_DONATION_NOTIFICATION_SERVER_ID
value: "297910194841583616" value: "{{ .Values.bot.config.debraNotificationServerId }}"
- name: WEEKLY_TEXT_SERVER_ID - name: WEEKLY_TEXT_SERVER_ID
value: "{{ .Values.bot.config.weeklyTextServerId }}" value: "{{ .Values.bot.config.weeklyTextServerId }}"
- name: TOKEN - name: TOKEN

View File

@@ -3,7 +3,7 @@ bot:
repository: harbor.sheldan.dev/sissi repository: harbor.sheldan.dev/sissi
pullPolicy: Always pullPolicy: Always
image: sissi-bot image: sissi-bot
tag: 1.5.11 tag: 1.5.16
livenessProbe: livenessProbe:
initialDelaySeconds: 60 initialDelaySeconds: 60
periodSeconds: 5 periodSeconds: 5
@@ -17,12 +17,13 @@ bot:
host: null host: null
config: config:
weeklyTextServerId: null weeklyTextServerId: null
debraNotificationServerId: null
restApi: restApi:
enabled: true enabled: true
repository: harbor.sheldan.dev/sissi repository: harbor.sheldan.dev/sissi
pullPolicy: Always pullPolicy: Always
image: sissi-rest-api image: sissi-rest-api
tag: 1.5.11 tag: 1.5.16
podAnnotations: {} podAnnotations: {}
podSecurityContext: {} podSecurityContext: {}
securityContext: {} securityContext: {}
@@ -62,7 +63,7 @@ privateRestApi:
repository: harbor.sheldan.dev/sissi repository: harbor.sheldan.dev/sissi
pullPolicy: Always pullPolicy: Always
image: sissi-private-rest-api image: sissi-private-rest-api
tag: 1.5.11 tag: 1.5.16
podAnnotations: {} podAnnotations: {}
podSecurityContext: {} podSecurityContext: {}
securityContext: {} securityContext: {}
@@ -93,23 +94,23 @@ templateDeployment:
repository: harbor.sheldan.dev/abstracto repository: harbor.sheldan.dev/abstracto
pullPolicy: Always pullPolicy: Always
image: abstracto-template-deployment image: abstracto-template-deployment
tag: 1.6.13 tag: 1.6.17
templateDeploymentData: templateDeploymentData:
repository: harbor.sheldan.dev/sissi repository: harbor.sheldan.dev/sissi
pullPolicy: Always pullPolicy: Always
image: sissi-template-data image: sissi-template-data
tag: 1.5.11 tag: 1.5.16
dbConfigDeployment: dbConfigDeployment:
enabled: true enabled: true
repository: harbor.sheldan.dev/abstracto repository: harbor.sheldan.dev/abstracto
pullPolicy: Always pullPolicy: Always
image: abstracto-db-deployment image: abstracto-db-deployment
tag: 1.6.13 tag: 1.6.17
dbConfigDeploymentData: dbConfigDeploymentData:
repository: harbor.sheldan.dev/sissi repository: harbor.sheldan.dev/sissi
pullPolicy: Always pullPolicy: Always
image: sissi-db-data image: sissi-db-data
tag: 1.5.11 tag: 1.5.16
dbCredentials: dbCredentials:
host: null host: null
port: null port: null

View File

@@ -3,7 +3,7 @@
<parent> <parent>
<groupId>dev.sheldan.sissi</groupId> <groupId>dev.sheldan.sissi</groupId>
<artifactId>deployment</artifactId> <artifactId>deployment</artifactId>
<version>1.5.12</version> <version>1.5.17-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent> <parent>
<groupId>dev.sheldan.sissi</groupId> <groupId>dev.sheldan.sissi</groupId>
<artifactId>sissi</artifactId> <artifactId>sissi</artifactId>
<version>1.5.12</version> <version>1.5.17-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -13,15 +13,16 @@
<groupId>dev.sheldan.sissi</groupId> <groupId>dev.sheldan.sissi</groupId>
<artifactId>sissi</artifactId> <artifactId>sissi</artifactId>
<name>Sissi</name> <name>Sissi</name>
<version>1.5.12</version> <version>1.5.17-SNAPSHOT</version>
<properties> <properties>
<maven.compiler.target>17</maven.compiler.target> <maven.compiler.target>17</maven.compiler.target>
<maven.compiler.source>17</maven.compiler.source> <maven.compiler.source>17</maven.compiler.source>
<abstracto.version>1.6.13</abstracto.version> <abstracto.version>1.6.17</abstracto.version>
<abstracto.templates.version>1.4.60</abstracto.templates.version> <abstracto.templates.version>1.4.63</abstracto.templates.version>
<apache-jena.version>4.9.0</apache-jena.version> <apache-jena.version>4.9.0</apache-jena.version>
<rssreader.version>3.5.0</rssreader.version> <rssreader.version>3.5.0</rssreader.version>
<jsoup.version>1.21.2</jsoup.version>
</properties> </properties>
<modules> <modules>
@@ -72,7 +73,7 @@
<connection>scm:git:${project.scm.url}</connection> <connection>scm:git:${project.scm.url}</connection>
<developerConnection>scm:git:${project.scm.url}</developerConnection> <developerConnection>scm:git:${project.scm.url}</developerConnection>
<url>https://github.com/Sheldan/Sissi.git</url> <url>https://github.com/Sheldan/Sissi.git</url>
<tag>sissi-1.5.12</tag> <tag>HEAD</tag>
</scm> </scm>
</project> </project>

View File

@@ -239,7 +239,7 @@ def rendering_donation_image(donation_stats, parameters):
height = parameters.font_size height = parameters.font_size
it = 0 it = 0
for donation in donations_to_draw: for donation in donations_to_draw:
name = donation['firstName'] if not donation['anonymous'] else 'anonym' name = donation['name'] if not donation['anonymous'] and 'name' in donation else 'anonym'
d1.text((0, height * it), f"{donation['donationAmount']}€ von {name}", fill=parameters.color, font=font) d1.text((0, height * it), f"{donation['donationAmount']}€ von {name}", fill=parameters.color, font=font)
it += 1 it += 1
return flask_utils.serve_pil_image(img) return flask_utils.serve_pil_image(img)

View File

@@ -0,0 +1,76 @@
{
<#assign mapping={
'bp': '340380695585095680',
'np': '400642855682572288',
'bk': '299162473775366144',
'mi': '400642854248120330',
'na': '400642590267146240',
'br': '400642587620278273',
'lo': '400643490020851712',
'lr': '400642584617418753',
'lm': '400642579881787402',
'bo': '400642539889229825',
'bm': '299162333668835328',
'gm': '400642460713484308',
'up': '299162129284726784',
'ap': '336786889589915659',
'dd': '336786578103992323',
'dr': '298790326943088670',
'ms': '298790213453479937',
'bs': '298790020192403456',
'di': '298790014974820356',
'in': '298789520084566018'
}>
<#assign groups={
'1': {'bp': 1, 'np': 2, 'bk': 3, 'mi': 4, 'na': 5, 'br': 6, 'lo': 7, 'lr': 8, 'lm': 9, 'bo': 10, 'bm': 11, 'gm': 12},
'2': {'up': 1, 'ap': 2},
'3': {'dd': 1, 'dr': 2},
'4': {'ms': 1, 'bs': 2},
'5': {'di': 1},
'6': {'in': 1}
}>
<#assign allowedRoleIds=[]>
<#assign reverseMapping={}>
<#list mapping as key, value>
<#assign allowedRoleIds=allowedRoleIds + [value]>
<#assign reverseMapping=reverseMapping + {value: key}>
</#list>
<#assign relevantRoles={}>
<#assign relevantRoleIds=[]>
<#list roles as role>
<#if allowedRoleIds?seq_contains(role.roleId?c)>
<#assign relevantRoles=relevantRoles + {role.roleId?c:role.roleName}>
<#assign relevantRoleIds=relevantRoleIds+[role.roleId?c]>
</#if>
</#list>
<#function is_printed role_id>
<#assign group={}>
<#assign found_prio=1>
<#list groups as key,members>
<#list members as roleshortcut,prio>
<#if role_id=mapping[roleshortcut]>
<#assign group=members>
<#assign found_prio=prio>
</#if>
</#list>
</#list>
<#assign print=true>
<#list group as shortcut,prio>
<#if relevantRoleIds?seq_contains(mapping[shortcut])>
<#if prio < found_prio>
<#assign print=false>
</#if>
</#if>
</#list>
<#return print>
</#function>
<#macro get_title key>
<#assign role_id=mapping[key]><#rt>
<#if is_printed(role_id) && relevantRoleIds?seq_contains(role_id)><#rt>
${relevantRoles[role_id]}<#rt>
</#if>
</#macro>
<#include "user_detail">
<#assign userText><@get_title 'bp'/><@get_title 'np'/><@get_title 'bk'/><@get_title 'mi'/><@get_title 'na'/><@get_title 'br'/><@get_title 'lo'/><@get_title 'lr'/><@get_title 'lm'/><@get_title 'bo'/><@get_title 'bm'/><@get_title 'gm'/><@get_title 'up'/><@get_title 'ap'/><@get_title 'dd'/><@get_title 'dr'/><@get_title 'di'/><@get_title 'in'/> ${user.name} <@get_title 'ms'/><@get_title 'bs'/> (${user.id?c})</#assign>
"additionalMessage": "<#compress><@safe_include "user_left_text"/></#compress>"
}

View File

@@ -3,7 +3,7 @@
<parent> <parent>
<groupId>dev.sheldan.sissi</groupId> <groupId>dev.sheldan.sissi</groupId>
<artifactId>sissi</artifactId> <artifactId>sissi</artifactId>
<version>1.5.12</version> <version>1.5.17-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -4,7 +4,7 @@
<parent> <parent>
<artifactId>customization-templates</artifactId> <artifactId>customization-templates</artifactId>
<groupId>dev.sheldan.sissi.templates</groupId> <groupId>dev.sheldan.sissi.templates</groupId>
<version>1.5.12</version> <version>1.5.17-SNAPSHOT</version>
</parent> </parent>
<artifactId>image-generation-customization-templates</artifactId> <artifactId>image-generation-customization-templates</artifactId>

View File

@@ -3,7 +3,7 @@
<parent> <parent>
<groupId>dev.sheldan.sissi.templates</groupId> <groupId>dev.sheldan.sissi.templates</groupId>
<artifactId>customization-templates</artifactId> <artifactId>customization-templates</artifactId>
<version>1.5.12</version> <version>1.5.17-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent> <parent>
<artifactId>sissi-templates</artifactId> <artifactId>sissi-templates</artifactId>
<groupId>dev.sheldan.sissi.templates</groupId> <groupId>dev.sheldan.sissi.templates</groupId>
<version>1.5.12</version> <version>1.5.17-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent> <parent>
<artifactId>module-templates</artifactId> <artifactId>module-templates</artifactId>
<groupId>dev.sheldan.sissi.templates</groupId> <groupId>dev.sheldan.sissi.templates</groupId>
<version>1.5.12</version> <version>1.5.17-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -13,7 +13,7 @@
,"fields": [ ,"fields": [
<#list donations as donation> <#list donations as donation>
{ {
"name": "<#if donation.anonymous><#include "donations_response_anonymous"><#else>${donation.firstName}</#if>", "name": "<#if donation.anonymous><#include "donations_response_anonymous"><#else>${donation.name}</#if>",
"value": "${donation.donationAmount}€", "value": "${donation.donationAmount}€",
"inline": true "inline": true
} }

View File

@@ -2,12 +2,14 @@
"embeds": [ "embeds": [
{ {
"title": { "title": {
<#assign donatorName=donation.donatorName> <#assign donatorName><#if donation.anonymous><#include "donations_response_anonymous"><#else>${donation.donatorName}</#if></#assign>
<#assign donationAmount=donation.amount> <#assign donationAmount=donation.amount>
"title": "<@safe_include "debra_donation_notification_embed_title"/>" "title": "<@safe_include "debra_donation_notification_embed_title"/>"
}, },
<#assign donationMessage=donation.message> <#if donation.message != 'gespendet'>
"description": "${donationMessage?json_string}", <#assign donationMessage=donation.message>
"description": "${donationMessage?json_string}",
</#if>
"fields": [ "fields": [
{ {
<#assign totalDonationAmount=totalDonationAmount> <#assign totalDonationAmount=totalDonationAmount>
@@ -24,7 +26,7 @@
"buttons": [ "buttons": [
{ {
"label": "<@safe_include "debra_donation_notification_link_button_label"/>", "label": "<@safe_include "debra_donation_notification_link_button_label"/>",
"url": "http://tiny.cc/schmetterling2024", "url": "https://tinyurl.com/debra25",
"buttonStyle": "link", "buttonStyle": "link",
"metaConfig": { "metaConfig": {
"persistCallback": false "persistCallback": false

View File

@@ -3,7 +3,7 @@
<parent> <parent>
<artifactId>module-templates</artifactId> <artifactId>module-templates</artifactId>
<groupId>dev.sheldan.sissi.templates</groupId> <groupId>dev.sheldan.sissi.templates</groupId>
<version>1.5.12</version> <version>1.5.17-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -17,20 +17,24 @@
{ {
<#assign time><@format_instant_long_date_time instant=meetupTime/></#assign> <#assign time><@format_instant_long_date_time instant=meetupTime/></#assign>
<#assign timeRelative><@format_instant_relative instant=meetupTime/></#assign> <#assign timeRelative><@format_instant_relative instant=meetupTime/></#assign>
<#if location?? && location != "%22%22">
"type": "section", "type": "section",
"components": [ "components": [
{ {
"type": "textDisplay", "type": "textDisplay",
"content": "<@safe_include "meetup_display_time_component"/>" "content": "<@safe_include "meetup_display_time_component"/>"
} }
] ],
<#if location?? && location != "%22%22"> "accessory": {
,"accessory": {
"type": "button", "type": "button",
"label": "<@safe_include "meetup_message_location_button_label"/>", "label": "<@safe_include "meetup_message_location_button_label"/>",
"url": "https://www.google.com/maps?q=${location?json_string}", "url": "https://www.google.com/maps?q=${location?json_string}",
"buttonStyle": "link" "buttonStyle": "link"
} }
<#else>
"type": "textDisplay",
"content": "<@safe_include "meetup_display_time_component"/>"
</#if> </#if>
} }
<#macro decision_component button_id button_style label_template content_template user> <#macro decision_component button_id button_style label_template content_template user>

View File

@@ -4,7 +4,7 @@
<parent> <parent>
<groupId>dev.sheldan.sissi.templates</groupId> <groupId>dev.sheldan.sissi.templates</groupId>
<artifactId>module-templates</artifactId> <artifactId>module-templates</artifactId>
<version>1.5.12</version> <version>1.5.17-SNAPSHOT</version>
</parent> </parent>
<artifactId>miepscord-templates</artifactId> <artifactId>miepscord-templates</artifactId>

View File

@@ -3,7 +3,7 @@
<parent> <parent>
<groupId>dev.sheldan.sissi.templates</groupId> <groupId>dev.sheldan.sissi.templates</groupId>
<artifactId>sissi-templates</artifactId> <artifactId>sissi-templates</artifactId>
<version>1.5.12</version> <version>1.5.17-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent> <parent>
<groupId>dev.sheldan.sissi.templates</groupId> <groupId>dev.sheldan.sissi.templates</groupId>
<artifactId>module-templates</artifactId> <artifactId>module-templates</artifactId>
<version>1.5.12</version> <version>1.5.17-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent> <parent>
<artifactId>module-templates</artifactId> <artifactId>module-templates</artifactId>
<groupId>dev.sheldan.sissi.templates</groupId> <groupId>dev.sheldan.sissi.templates</groupId>
<version>1.5.12</version> <version>1.5.17-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent> <parent>
<groupId>dev.sheldan.sissi.templates</groupId> <groupId>dev.sheldan.sissi.templates</groupId>
<artifactId>templates</artifactId> <artifactId>templates</artifactId>
<version>1.5.12</version> <version>1.5.17-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent> <parent>
<groupId>dev.sheldan.sissi.templates</groupId> <groupId>dev.sheldan.sissi.templates</groupId>
<artifactId>template-overrides</artifactId> <artifactId>template-overrides</artifactId>
<version>1.5.12</version> <version>1.5.17-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent> <parent>
<groupId>dev.sheldan.sissi.templates</groupId> <groupId>dev.sheldan.sissi.templates</groupId>
<artifactId>template-overrides</artifactId> <artifactId>template-overrides</artifactId>
<version>1.5.12</version> <version>1.5.17-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -1,5 +1,5 @@
{ {
<#assign userMention>${member.asMention}</#assign> <#assign userMention>${member.asMention}</#assign>
<#assign user>${member.user.name} (${member.asMention}: ${member.id})</#assign> <#assign userText>${member.user.name} (${member.asMention}: ${member.id?c})</#assign>
"additionalMessage": "<@safe_include "user_joined_text"/>" "additionalMessage": "<@safe_include "user_joined_text"/>"
} }

View File

@@ -1,5 +1,5 @@
{ {
<#include "user_detail"> <#include "user_detail">
<#assign user><@user_detail user=user/></#assign> <#assign userText>${user.name} (${user.userMention}: ${user.id?c})</#assign>
"additionalMessage": "<@safe_include "user_left_text"/>" "additionalMessage": "<@safe_include "user_left_text"/>"
} }

View File

@@ -3,7 +3,7 @@
<parent> <parent>
<groupId>dev.sheldan.sissi.templates</groupId> <groupId>dev.sheldan.sissi.templates</groupId>
<artifactId>template-overrides</artifactId> <artifactId>template-overrides</artifactId>
<version>1.5.12</version> <version>1.5.17-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent> <parent>
<artifactId>sissi-templates</artifactId> <artifactId>sissi-templates</artifactId>
<groupId>dev.sheldan.sissi.templates</groupId> <groupId>dev.sheldan.sissi.templates</groupId>
<version>1.5.12</version> <version>1.5.17-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent> <parent>
<groupId>dev.sheldan.sissi.templates</groupId> <groupId>dev.sheldan.sissi.templates</groupId>
<artifactId>template-overrides</artifactId> <artifactId>template-overrides</artifactId>
<version>1.5.12</version> <version>1.5.17-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent> <parent>
<groupId>dev.sheldan.sissi.templates.translations</groupId> <groupId>dev.sheldan.sissi.templates.translations</groupId>
<artifactId>customization-translations</artifactId> <artifactId>customization-translations</artifactId>
<version>1.5.12</version> <version>1.5.17-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent> <parent>
<artifactId>sissi-translations</artifactId> <artifactId>sissi-translations</artifactId>
<groupId>dev.sheldan.sissi.templates.translations</groupId> <groupId>dev.sheldan.sissi.templates.translations</groupId>
<version>1.5.12</version> <version>1.5.17-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent> <parent>
<artifactId>module-translations</artifactId> <artifactId>module-translations</artifactId>
<groupId>dev.sheldan.sissi.templates.translations</groupId> <groupId>dev.sheldan.sissi.templates.translations</groupId>
<version>1.5.12</version> <version>1.5.17-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -1 +1 @@
Aktuell wurden **${donationAmount} Euro** für Debra Austria gespendet. Spende auch du unter https://tiny.cc/schmetterling2024. Aktuell wurden **${donationAmount} Euro** für Debra Austria gespendet. Spende auch du unter https://tinyurl.com/debra25.

View File

@@ -10,7 +10,7 @@ Alle Grafiken von diesem und den letzten Jahren findest du in diesem Ordner. All
Spendenlink Spendenlink
Wir empfehlen neben dem Einrichten einer 'Kachel' auch, dass ihr einen !spenden Befehl bei eurem Bot (nightbot, moobot, self hosted etc.) hinzufügt. Wir empfehlen neben dem Einrichten einer 'Kachel' auch, dass ihr einen !spenden Befehl bei eurem Bot (nightbot, moobot, self hosted etc.) hinzufügt.
Bitte verlinke dabei auf <https://tiny.cc/schmetterling2024> Bitte verlinke dabei auf <https://tinyurl.com/debra25>
Live-ping am Discord Live-ping am Discord
Damit wir deinen Account zur Going Live Liste hinzufügen können, musst du uns nach der Einrichtung des Streams bescheid geben. Damit wir deinen Account zur Going Live Liste hinzufügen können, musst du uns nach der Einrichtung des Streams bescheid geben.

View File

@@ -1 +1 @@
Spende auch du für Debra Austria unter http://tiny.cc/schmetterling2024. Spende auch du für Debra Austria unter https://tinyurl.com/debra25.

View File

@@ -1 +1 @@
Also donate for Debra austria via http://tiny.cc/schmetterling2024. Also donate for Debra austria via https://tinyurl.com/debra25.

View File

@@ -3,7 +3,7 @@
<parent> <parent>
<groupId>dev.sheldan.sissi.templates.translations</groupId> <groupId>dev.sheldan.sissi.templates.translations</groupId>
<artifactId>module-translations</artifactId> <artifactId>module-translations</artifactId>
<version>1.5.12</version> <version>1.5.17-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -4,7 +4,7 @@
<parent> <parent>
<groupId>dev.sheldan.sissi.templates.translations</groupId> <groupId>dev.sheldan.sissi.templates.translations</groupId>
<artifactId>module-translations</artifactId> <artifactId>module-translations</artifactId>
<version>1.5.12</version> <version>1.5.17-SNAPSHOT</version>
</parent> </parent>
<artifactId>miepscord-translations</artifactId> <artifactId>miepscord-translations</artifactId>

View File

@@ -3,7 +3,7 @@
<parent> <parent>
<groupId>dev.sheldan.sissi.templates.translations</groupId> <groupId>dev.sheldan.sissi.templates.translations</groupId>
<artifactId>sissi-translations</artifactId> <artifactId>sissi-translations</artifactId>
<version>1.5.12</version> <version>1.5.17-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent> <parent>
<groupId>dev.sheldan.sissi.templates.translations</groupId> <groupId>dev.sheldan.sissi.templates.translations</groupId>
<artifactId>module-translations</artifactId> <artifactId>module-translations</artifactId>
<version>1.5.12</version> <version>1.5.17-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent> <parent>
<artifactId>module-translations</artifactId> <artifactId>module-translations</artifactId>
<groupId>dev.sheldan.sissi.templates.translations</groupId> <groupId>dev.sheldan.sissi.templates.translations</groupId>
<version>1.5.12</version> <version>1.5.17-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent> <parent>
<groupId>dev.sheldan.sissi.templates</groupId> <groupId>dev.sheldan.sissi.templates</groupId>
<artifactId>templates</artifactId> <artifactId>templates</artifactId>
<version>1.5.12</version> <version>1.5.17-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent> <parent>
<groupId>dev.sheldan.sissi.templates.translations.overrides</groupId> <groupId>dev.sheldan.sissi.templates.translations.overrides</groupId>
<artifactId>translation-overrides</artifactId> <artifactId>translation-overrides</artifactId>
<version>1.5.12</version> <version>1.5.17-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent> <parent>
<groupId>dev.sheldan.sissi.templates.translations.overrides</groupId> <groupId>dev.sheldan.sissi.templates.translations.overrides</groupId>
<artifactId>translation-overrides</artifactId> <artifactId>translation-overrides</artifactId>
<version>1.5.12</version> <version>1.5.17-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent> <parent>
<groupId>dev.sheldan.sissi.templates.translations.overrides</groupId> <groupId>dev.sheldan.sissi.templates.translations.overrides</groupId>
<artifactId>translation-overrides</artifactId> <artifactId>translation-overrides</artifactId>
<version>1.5.12</version> <version>1.5.17-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent> <parent>
<groupId>dev.sheldan.sissi.templates.translations.overrides</groupId> <groupId>dev.sheldan.sissi.templates.translations.overrides</groupId>
<artifactId>translation-overrides</artifactId> <artifactId>translation-overrides</artifactId>
<version>1.5.12</version> <version>1.5.17-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent> <parent>
<groupId>dev.sheldan.sissi.templates.translations</groupId> <groupId>dev.sheldan.sissi.templates.translations</groupId>
<artifactId>sissi-translations</artifactId> <artifactId>sissi-translations</artifactId>
<version>1.5.12</version> <version>1.5.17-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>