Compare commits

...

24 Commits

Author SHA1 Message Date
release-bot
072c192e4f [maven-release-plugin] prepare release v1.6.28 2026-05-15 11:29:33 +00:00
Sheldan
be5cb132ea [AB-xxx] fixing offset for grrr meme 2026-05-15 13:25:47 +02:00
release-bot
6deb5aad77 Commit from GitHub Actions (Publishes a new version of abstracto) 2026-05-15 10:55:51 +00:00
release-bot
32e0c1dc83 [maven-release-plugin] prepare for next development iteration 2026-05-15 10:43:07 +00:00
release-bot
f0a5fbd059 [maven-release-plugin] prepare release v1.6.27 2026-05-15 10:43:05 +00:00
Sheldan
8024eb56b0 [AB-xxx] fixing typo 2026-05-15 12:40:20 +02:00
release-bot
87937f48b7 Commit from GitHub Actions (Publishes a new version of abstracto) 2026-05-15 09:16:26 +00:00
release-bot
6dda4132f6 [maven-release-plugin] prepare for next development iteration 2026-05-15 09:00:15 +00:00
release-bot
67fdfe3b54 [maven-release-plugin] prepare release v1.6.26 2026-05-15 09:00:12 +00:00
Sheldan
0586ade8d8 [AB-xxx] filtering current section from past sections in twitch stream notifications to not duplicate the information in case of a refresh 2026-05-15 00:26:52 +02:00
Sheldan
ae91c8ee4d [AB-xxx] adding grrr image generation 2026-05-15 00:20:52 +02:00
release-bot
0cec5284b4 Commit from GitHub Actions (Publishes a new version of abstracto) 2026-05-02 22:46:19 +00:00
release-bot
51e0da06ae [maven-release-plugin] prepare for next development iteration 2026-05-02 22:35:37 +00:00
release-bot
f4b048d18b [maven-release-plugin] prepare release v1.6.25 2026-05-02 22:35:35 +00:00
Sheldan
6addd5939b [AB-xxx] adding honeypot message feature to ban members that message a certain channel 2026-05-03 00:31:56 +02:00
Sheldan
dafde2d8f6 [AB-xxx] refactoring enable/disableMode to the modes coming from the feature instead of the ones already present in the server 2026-05-03 00:29:28 +02:00
Sheldan
96cbe2db87 [AB-xxx] adding ability to refresh twitch stream notification texts 2026-05-03 00:28:02 +02:00
Sheldan
2ae2542c71 [AB-xxx] changing timestamp used for updated in modmail reminder job 2026-05-02 13:58:51 +02:00
release-bot
a69d4c25ff Commit from GitHub Actions (Publishes a new version of abstracto) 2026-04-26 21:26:13 +00:00
release-bot
fba5adf573 [maven-release-plugin] prepare for next development iteration 2026-04-26 21:14:22 +00:00
release-bot
dd21390a60 [maven-release-plugin] prepare release v1.6.24 2026-04-26 21:14:20 +00:00
Sheldan
790cca7278 [AB-xxx] changing duration for reminder snooze, so that it doesnt add the duration _after_ the snooze again, the snooze is intended to be the duration at which the reminders start again
fixing message embed cleanup job not being able to deal with missing channels
2026-04-26 22:58:08 +02:00
release-bot
52f6fd148e Commit from GitHub Actions (Publishes a new version of abstracto) 2026-04-25 21:41:51 +00:00
release-bot
708703fc1f [maven-release-plugin] prepare for next development iteration 2026-04-25 21:30:06 +00:00
115 changed files with 524 additions and 129 deletions

2
.env
View File

@@ -1,2 +1,2 @@
REGISTRY_PREFIX=harbor.sheldan.dev/abstracto/
VERSION=1.6.22
VERSION=1.6.27

View File

@@ -3,7 +3,7 @@
<parent>
<artifactId>anti-raid</artifactId>
<groupId>dev.sheldan.abstracto.modules</groupId>
<version>1.6.23</version>
<version>1.6.28</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent>
<artifactId>anti-raid</artifactId>
<groupId>dev.sheldan.abstracto.modules</groupId>
<version>1.6.23</version>
<version>1.6.28</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent>
<artifactId>abstracto-modules</artifactId>
<groupId>dev.sheldan.abstracto.modules</groupId>
<version>1.6.23</version>
<version>1.6.28</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent>
<groupId>dev.sheldan.abstracto.modules</groupId>
<artifactId>assignable-roles</artifactId>
<version>1.6.23</version>
<version>1.6.28</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent>
<groupId>dev.sheldan.abstracto.modules</groupId>
<artifactId>assignable-roles</artifactId>
<version>1.6.23</version>
<version>1.6.28</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>assignable-roles-int</artifactId>

View File

@@ -3,7 +3,7 @@
<parent>
<groupId>dev.sheldan.abstracto.modules</groupId>
<artifactId>abstracto-modules</artifactId>
<version>1.6.23</version>
<version>1.6.28</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent>
<groupId>dev.sheldan.abstracto.modules</groupId>
<artifactId>custom-command</artifactId>
<version>1.6.23</version>
<version>1.6.28</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent>
<groupId>dev.sheldan.abstracto.modules</groupId>
<artifactId>custom-command</artifactId>
<version>1.6.23</version>
<version>1.6.28</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent>
<artifactId>abstracto-modules</artifactId>
<groupId>dev.sheldan.abstracto.modules</groupId>
<version>1.6.23</version>
<version>1.6.28</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent>
<groupId>dev.sheldan.abstracto.modules</groupId>
<artifactId>dynamic-activity</artifactId>
<version>1.6.23</version>
<version>1.6.28</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent>
<artifactId>dynamic-activity</artifactId>
<groupId>dev.sheldan.abstracto.modules</groupId>
<version>1.6.23</version>
<version>1.6.28</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent>
<artifactId>abstracto-modules</artifactId>
<groupId>dev.sheldan.abstracto.modules</groupId>
<version>1.6.23</version>
<version>1.6.28</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent>
<artifactId>entertainment</artifactId>
<groupId>dev.sheldan.abstracto.modules</groupId>
<version>1.6.23</version>
<version>1.6.28</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent>
<artifactId>entertainment</artifactId>
<groupId>dev.sheldan.abstracto.modules</groupId>
<version>1.6.23</version>
<version>1.6.28</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent>
<artifactId>abstracto-modules</artifactId>
<groupId>dev.sheldan.abstracto.modules</groupId>
<version>1.6.23</version>
<version>1.6.28</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent>
<groupId>dev.sheldan.abstracto.modules</groupId>
<artifactId>experience-tracking</artifactId>
<version>1.6.23</version>
<version>1.6.28</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent>
<groupId>dev.sheldan.abstracto.modules</groupId>
<artifactId>experience-tracking</artifactId>
<version>1.6.23</version>
<version>1.6.28</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent>
<groupId>dev.sheldan.abstracto.modules</groupId>
<artifactId>abstracto-modules</artifactId>
<version>1.6.23</version>
<version>1.6.28</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -4,7 +4,7 @@
<parent>
<groupId>dev.sheldan.abstracto.modules</groupId>
<artifactId>giveaway</artifactId>
<version>1.6.23</version>
<version>1.6.28</version>
</parent>
<artifactId>giveaway-impl</artifactId>

View File

@@ -4,7 +4,7 @@
<parent>
<groupId>dev.sheldan.abstracto.modules</groupId>
<artifactId>giveaway</artifactId>
<version>1.6.23</version>
<version>1.6.28</version>
</parent>
<artifactId>giveaway-int</artifactId>

View File

@@ -4,7 +4,7 @@
<parent>
<groupId>dev.sheldan.abstracto.modules</groupId>
<artifactId>abstracto-modules</artifactId>
<version>1.6.23</version>
<version>1.6.28</version>
</parent>
<artifactId>giveaway</artifactId>

View File

@@ -4,7 +4,7 @@
<parent>
<artifactId>image-generation</artifactId>
<groupId>dev.sheldan.abstracto.modules</groupId>
<version>1.6.23</version>
<version>1.6.28</version>
</parent>
<artifactId>image-generation-impl</artifactId>

View File

@@ -0,0 +1,134 @@
package dev.sheldan.abstracto.imagegeneration.command;
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.config.UserCommandConfig;
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.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.AttachedFile;
import dev.sheldan.abstracto.core.templating.model.MessageToSend;
import dev.sheldan.abstracto.core.templating.service.TemplateService;
import dev.sheldan.abstracto.core.utils.FileService;
import dev.sheldan.abstracto.core.utils.FutureUtils;
import dev.sheldan.abstracto.imagegeneration.config.ImageGenerationFeatureDefinition;
import dev.sheldan.abstracto.imagegeneration.config.ImageGenerationSlashCommandNames;
import dev.sheldan.abstracto.imagegeneration.service.ImageGenerationService;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class Grrr extends AbstractConditionableCommand {
@Autowired
private ImageGenerationService imageGenerationService;
@Autowired
private TemplateService templateService;
@Autowired
private ChannelService channelService;
@Autowired
private FileService fileService;
@Autowired
private InteractionService interactionService;
@Autowired
private SlashCommandParameterService slashCommandParameterService;
private static final String GRRR_EMBED_TEMPLATE_KEY = "grrr_response";
public static final String TEXT_PARAMETER_KEY = "text";
@Override
public CompletableFuture<CommandResult> executeAsync(CommandContext commandContext) {
List<Object> parameters = commandContext.getParameters().getParameters();
String text = (String) parameters.get(0);
File grrrFile = imageGenerationService.getGrrrImage(text);
MessageToSend messageToSend = templateService.renderEmbedTemplate(GRRR_EMBED_TEMPLATE_KEY, new Object(), commandContext.getGuild().getIdLong());
// template support does not support binary files
AttachedFile file = AttachedFile
.builder()
.file(grrrFile)
.fileName("grrr.png")
.build();
messageToSend.getAttachedFiles().add(file);
return FutureUtils.toSingleFutureGeneric(channelService.sendMessageToSendToChannel(messageToSend, commandContext.getChannel()))
.thenAccept(unused -> fileService.safeDeleteIgnoreException(messageToSend.getAttachedFiles().get(0).getFile()))
.thenApply(unused -> CommandResult.fromIgnored());
}
@Override
public CompletableFuture<CommandResult> executeSlash(SlashCommandInteractionEvent event) {
event.deferReply().queue();
String text = slashCommandParameterService.getCommandOption(TEXT_PARAMETER_KEY, event, String.class);
File grrrFile = imageGenerationService.getGrrrImage(text);
MessageToSend messageToSend = templateService.renderEmbedTemplate(GRRR_EMBED_TEMPLATE_KEY, new Object(), event.getGuild().getIdLong());
// template support does not support binary files
AttachedFile file = AttachedFile
.builder()
.file(grrrFile)
.fileName("grrr.png")
.build();
messageToSend.getAttachedFiles().add(file);
return FutureUtils.toSingleFutureGeneric(interactionService.sendMessageToInteraction(messageToSend, event.getHook()))
.thenAccept(unused -> fileService.safeDeleteIgnoreException(messageToSend.getAttachedFiles().get(0).getFile()))
.thenApply(unused -> CommandResult.fromIgnored());
}
@Override
public CommandConfiguration getConfiguration() {
List<Parameter> parameters = new ArrayList<>();
Parameter textParameter = Parameter
.builder()
.name(TEXT_PARAMETER_KEY)
.type(String.class)
.templated(true)
.build();
parameters.add(textParameter);
HelpInfo helpInfo = HelpInfo
.builder()
.templated(true)
.build();
SlashCommandConfig slashCommandConfig = SlashCommandConfig
.builder()
.enabled(true)
.userInstallable(true)
.userCommandConfig(UserCommandConfig.all())
.rootCommandName(ImageGenerationSlashCommandNames.IMAGE_GENERATION)
.groupName("memes")
.commandName("grrr")
.build();
return CommandConfiguration.builder()
.name("grrr")
.module(UtilityModuleDefinition.UTILITY)
.templated(true)
.supportsEmbedException(true)
.async(true)
.slashCommandConfig(slashCommandConfig)
.parameters(parameters)
.help(helpInfo)
.build();
}
@Override
public FeatureDefinition getFeature() {
return ImageGenerationFeatureDefinition.IMAGE_GENERATION;
}
}

View File

@@ -27,6 +27,10 @@ public class ImageGenerationServiceBean implements ImageGenerationService {
@Value("${abstracto.feature.imagegeneration.amongusText.url}")
private String amongusTextUrl;
@Value("${abstracto.feature.imagegeneration.grrr.url}")
private String grrrUrl;
@Autowired
private HttpService httpService;
@@ -68,4 +72,13 @@ public class ImageGenerationServiceBean implements ImageGenerationService {
}
}
@Override
public File getGrrrImage(String text) {
try {
return httpService.downloadFileToTempFile(grrrUrl.replace("{1}", text));
} catch (IOException | RequestException e) {
throw new AbstractoRunTimeException(String.format("Failed to download grrr image for text %s with error %s", text, e.getMessage()));
}
}
}

View File

@@ -11,3 +11,5 @@ abstracto.feature.imagegeneration.bonk.url=http://${PRIVATE_REST_API_HOST}:${PRI
abstracto.feature.imagegeneration.bonk.imagesize=128
abstracto.feature.imagegeneration.amongusText.url=http://${PRIVATE_REST_API_HOST}:${PRIVATE_REST_API_PORT}/memes/amongus/text?text={1}
abstracto.feature.imagegeneration.grrr.url=http://${PRIVATE_REST_API_HOST}:${PRIVATE_REST_API_PORT}/memes/grrr/text?text={1}

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="seedData/data.xml" relativeToChangelogFile="true"/>
</databaseChangeLog>

View File

@@ -0,0 +1,16 @@
<?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" >
<property name="utilityModule" value="(SELECT id FROM module WHERE name = 'utility')"/>
<property name="imageGenerationFeature" value="(SELECT id FROM feature WHERE key = 'imageGeneration')"/>
<changeSet author="Sheldan" id="grrr-command">
<insert tableName="command">
<column name="name" value="grrr"/>
<column name="module_id" valueComputed="${utilityModule}"/>
<column name="feature_id" valueComputed="${imageGenerationFeature}"/>
</insert>
</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="command.xml" relativeToChangelogFile="true"/>
</databaseChangeLog>

View File

@@ -5,4 +5,5 @@
<include file="1.5.15/collection.xml" relativeToChangelogFile="true"/>
<include file="1.5.19/collection.xml" relativeToChangelogFile="true"/>
<include file="1.5.22/collection.xml" relativeToChangelogFile="true"/>
<include file="1.6.26/collection.xml" relativeToChangelogFile="true"/>
</databaseChangeLog>

View File

@@ -4,7 +4,7 @@
<parent>
<artifactId>image-generation</artifactId>
<groupId>dev.sheldan.abstracto.modules</groupId>
<version>1.6.23</version>
<version>1.6.28</version>
</parent>
<artifactId>image-generation-int</artifactId>

View File

@@ -7,4 +7,5 @@ public interface ImageGenerationService {
File getPatGif(String imageUrl);
File getBonkGif(String imageUrl);
File getAmongusTextImage(String text);
File getGrrrImage(String text);
}

View File

@@ -4,7 +4,7 @@
<parent>
<groupId>dev.sheldan.abstracto.modules</groupId>
<artifactId>abstracto-modules</artifactId>
<version>1.6.23</version>
<version>1.6.28</version>
</parent>
<artifactId>image-generation</artifactId>

View File

@@ -3,7 +3,7 @@
<parent>
<artifactId>invite-filter</artifactId>
<groupId>dev.sheldan.abstracto.modules</groupId>
<version>1.6.23</version>
<version>1.6.28</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent>
<artifactId>invite-filter</artifactId>
<groupId>dev.sheldan.abstracto.modules</groupId>
<version>1.6.23</version>
<version>1.6.28</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -18,7 +18,7 @@
<dependency>
<groupId>dev.sheldan.abstracto.modules</groupId>
<artifactId>moderation-int</artifactId>
<version>1.6.23</version>
<version>1.6.28</version>
<scope>compile</scope>
</dependency>
</dependencies>

View File

@@ -3,7 +3,7 @@
<parent>
<artifactId>abstracto-modules</artifactId>
<groupId>dev.sheldan.abstracto.modules</groupId>
<version>1.6.23</version>
<version>1.6.28</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent>
<artifactId>link-embed</artifactId>
<groupId>dev.sheldan.abstracto.modules</groupId>
<version>1.6.23</version>
<version>1.6.28</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -26,9 +26,11 @@ import dev.sheldan.abstracto.linkembed.service.management.MessageEmbedPostManage
import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.User;
import net.dv8tion.jda.api.entities.channel.middleman.GuildChannel;
import net.dv8tion.jda.api.entities.channel.middleman.GuildMessageChannel;
import net.dv8tion.jda.api.interactions.commands.CommandInteraction;
import org.apache.commons.lang3.tuple.Pair;
import org.checkerframework.checker.units.qual.A;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@@ -191,11 +193,20 @@ public class MessageEmbedServiceBean implements MessageEmbedService {
.builder()
.message(embeddedMessage)
.build();
MessageToSend messageToSend =
templateService.renderEmbedTemplate(MESSAGE_EMBED_CLEANUP_REPLACEMENT_TEMPLATE, model, embeddingMessage.getServerId());
return channelService.editMessageInAChannelFuture(messageToSend, embeddingMessage.getServerId(), embeddingMessage.getChannelId(),
embeddingMessage.getMessageId());
}).toList();
Optional<GuildChannel> existingChannel =
channelService.getGuildChannelFromServerOptional(embeddingMessage.getServerId(), embeddingMessage.getChannelId());
// if the channel doesnt exist, we dont need to cleanup
if(existingChannel.isPresent()) {
MessageToSend messageToSend =
templateService.renderEmbedTemplate(MESSAGE_EMBED_CLEANUP_REPLACEMENT_TEMPLATE, model, embeddingMessage.getServerId());
return channelService.editMessageInAChannelFuture(messageToSend, embeddingMessage.getServerId(), embeddingMessage.getChannelId(),
embeddingMessage.getMessageId());
} else {
return null;
}
})
.filter(Objects::nonNull)
.toList();
return FutureUtils.toSingleFutureGeneric(editList).whenComplete((unused, throwable) -> {
if(throwable != null) {
log.warn("Failed to cleanup embedded messages..", throwable);

View File

@@ -3,7 +3,7 @@
<parent>
<artifactId>link-embed</artifactId>
<groupId>dev.sheldan.abstracto.modules</groupId>
<version>1.6.23</version>
<version>1.6.28</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent>
<artifactId>abstracto-modules</artifactId>
<groupId>dev.sheldan.abstracto.modules</groupId>
<version>1.6.23</version>
<version>1.6.28</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent>
<artifactId>logging</artifactId>
<groupId>dev.sheldan.abstracto.modules</groupId>
<version>1.6.23</version>
<version>1.6.28</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent>
<artifactId>logging</artifactId>
<groupId>dev.sheldan.abstracto.modules</groupId>
<version>1.6.23</version>
<version>1.6.28</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent>
<artifactId>abstracto-modules</artifactId>
<groupId>dev.sheldan.abstracto.modules</groupId>
<version>1.6.23</version>
<version>1.6.28</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent>
<groupId>dev.sheldan.abstracto.modules</groupId>
<artifactId>moderation</artifactId>
<version>1.6.23</version>
<version>1.6.28</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -18,7 +18,7 @@ import dev.sheldan.abstracto.moderation.config.ModerationModuleDefinition;
import dev.sheldan.abstracto.moderation.config.ModerationSlashCommandNames;
import dev.sheldan.abstracto.moderation.config.feature.HoneyPotFeatureConfig;
import dev.sheldan.abstracto.moderation.config.feature.ModerationFeatureDefinition;
import dev.sheldan.abstracto.moderation.listener.HoneyPotServiceBean;
import dev.sheldan.abstracto.moderation.service.HoneyPotServiceBean;
import dev.sheldan.abstracto.moderation.model.template.command.HoneyPotBanResponseModel;
import java.time.Duration;
import java.time.Instant;
@@ -98,7 +98,7 @@ public class HoneyPotBan extends AbstractConditionableCommand {
.toList();
Role honeyPotRole = guild.getRoleById(honeyPotServiceBean.getHoneyPotRoleId(guild.getIdLong()));
List<CompletableFuture<Void>> futures = currentMembersWithHoneypotRole.stream().map(member ->
honeyPotServiceBean.banForHoneyPot(member, honeyPotRole)
honeyPotServiceBean.banForHoneyPotRole(member, honeyPotRole)
).toList();
Integer memberCount = currentMembersWithHoneypotRole.size();
CompletableFutureList<Void> futureList = new CompletableFutureList<>(futures);

View File

@@ -0,0 +1,61 @@
package dev.sheldan.abstracto.moderation.listener;
import dev.sheldan.abstracto.core.config.FeatureDefinition;
import dev.sheldan.abstracto.core.config.FeatureMode;
import dev.sheldan.abstracto.core.listener.DefaultListenerResult;
import dev.sheldan.abstracto.core.listener.async.jda.AsyncMessageReceivedListener;
import dev.sheldan.abstracto.core.models.listener.MessageReceivedModel;
import dev.sheldan.abstracto.core.service.ConfigService;
import dev.sheldan.abstracto.core.service.MessageService;
import dev.sheldan.abstracto.moderation.config.feature.HoneyPotFeatureConfig;
import dev.sheldan.abstracto.moderation.config.feature.ModerationFeatureDefinition;
import dev.sheldan.abstracto.moderation.config.feature.mode.HoneypotMode;
import dev.sheldan.abstracto.moderation.service.HoneyPotServiceBean;
import java.util.List;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
@Slf4j
public class HoneyPotMessageListener implements AsyncMessageReceivedListener {
@Autowired
private ConfigService configService;
@Autowired
private HoneyPotServiceBean honeyPotServiceBean;
@Autowired
private MessageService messageService;
@Override
public DefaultListenerResult execute(MessageReceivedModel model) {
Long honeyPotChannel = configService.getLongValueOrConfigDefault(HoneyPotFeatureConfig.HONEYPOT_CHANNEL, model.getServerId());
if(honeyPotChannel == 0) {
return DefaultListenerResult.IGNORED;
}
if(model.getMessage().getChannelId().equals(honeyPotChannel.toString())) {
boolean honeyPotActivated = honeyPotServiceBean.fellIntoHoneyPotIgnoringJoinDate(model.getServerId(), model.getMessage().getMember());
if(honeyPotActivated) {
log.info("Banning user {} in guild {} due to a message in channel {}.", model.getMessage().getAuthor().getIdLong(), model.getServerId(), honeyPotChannel);
honeyPotServiceBean.banForHoneyPotMessage(model.getMessage().getMember(), honeyPotChannel);
} else {
log.info("NOT banning user {} in guild {} due to a message in honeypot channel {}.", model.getMessage().getAuthor().getIdLong(), model.getServerId(), honeyPotChannel);
messageService.deleteMessage(model.getMessage());
}
return DefaultListenerResult.PROCESSED;
}
return DefaultListenerResult.IGNORED;
}
@Override
public FeatureDefinition getFeature() {
return ModerationFeatureDefinition.HONEYPOT;
}
@Override
public List<FeatureMode> getFeatureModeLimitations() {
return List.of(HoneypotMode.MESSAGE);
}
}

View File

@@ -1,12 +1,15 @@
package dev.sheldan.abstracto.moderation.listener;
import dev.sheldan.abstracto.core.config.FeatureDefinition;
import dev.sheldan.abstracto.core.config.FeatureMode;
import dev.sheldan.abstracto.core.config.ListenerPriority;
import dev.sheldan.abstracto.core.listener.DefaultListenerResult;
import dev.sheldan.abstracto.core.listener.sync.jda.RoleAddedListener;
import dev.sheldan.abstracto.core.models.listener.RoleAddedModel;
import dev.sheldan.abstracto.core.service.RoleService;
import dev.sheldan.abstracto.moderation.config.feature.ModerationFeatureDefinition;
import dev.sheldan.abstracto.moderation.config.feature.mode.HoneypotMode;
import dev.sheldan.abstracto.moderation.service.HoneyPotServiceBean;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
@@ -37,7 +40,7 @@ public class HoneyPotRoleAddedListener implements RoleAddedListener {
boolean fellIntoHoneyPot = honeyPotServiceBean.fellIntoHoneyPot(model.getServerId(), model.getTargetMember());
if (fellIntoHoneyPot) {
log.info("Banning user {} in guild {} due to role {}.", model.getTargetUser().getUserId(), model.getTargetUser().getServerId(), model.getRoleId());
honeyPotServiceBean.banForHoneyPot(model.getTargetMember(), model.getRole());
honeyPotServiceBean.banForHoneyPotRole(model.getTargetMember(), model.getRole());
} else {
log.info("User {} in server {} will not get banned by honeypot. All existing roles besides {} will be removed.",
model.getTargetUser().getUserId(), model.getTargetUser().getServerId(), honeyPotRoleId);
@@ -83,4 +86,8 @@ public class HoneyPotRoleAddedListener implements RoleAddedListener {
return ListenerPriority.MEDIUM;
}
@Override
public List<FeatureMode> getFeatureModeLimitations() {
return List.of(HoneypotMode.ROLE);
}
}

View File

@@ -1,4 +1,4 @@
package dev.sheldan.abstracto.moderation.listener;
package dev.sheldan.abstracto.moderation.service;
import dev.sheldan.abstracto.core.models.ConditionContextInstance;
import dev.sheldan.abstracto.core.models.ServerUser;
@@ -13,7 +13,6 @@ import dev.sheldan.abstracto.core.service.management.UserInServerManagementServi
import dev.sheldan.abstracto.core.templating.service.TemplateService;
import dev.sheldan.abstracto.moderation.config.feature.HoneyPotFeatureConfig;
import dev.sheldan.abstracto.moderation.model.listener.HoneyPotReasonModel;
import dev.sheldan.abstracto.moderation.service.BanService;
import java.time.Duration;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
@@ -68,11 +67,33 @@ public class HoneyPotServiceBean {
return !allowed;
}
public boolean fellIntoHoneyPotIgnoringJoinDate(Long serverId, Member member) {
Integer levelToSkipBan = configService.getLongValueOrConfigDefault(HoneyPotFeatureConfig.HONEYPOT_IGNORED_LEVEL, serverId).intValue();
boolean allowed = userHasLevel(member, levelToSkipBan);
return !allowed;
}
public List<Member> getCurrentMembersWithHoneypotRole(Guild guild) {
return memberService.getMembersWithRole(guild.getIdLong(), getHoneyPotRoleId(guild.getIdLong()));
}
public CompletableFuture<Void> banForHoneyPot(Member targetMember, Role role) {
public CompletableFuture<Void> banForHoneyPotMessage(Member targetMember, Long channelId) {
HoneyPotReasonModel reasonModel = HoneyPotReasonModel
.builder()
.memberDisplay(MemberDisplay.fromMember(targetMember))
.build();
ServerUser bannedUser = ServerUser.fromMember(targetMember);
String banReason = templateService.renderTemplate(HONEYPOT_BAN_REASON_TEMPLATE, reasonModel, bannedUser.getServerId());
return banService.banUserWithNotification(bannedUser, banReason, ServerUser.fromMember(targetMember.getGuild().getSelfMember()),
targetMember.getGuild(), Duration.ofDays(7)).thenAccept(banResult -> {
log.info("Banned user {} in guild {} due to a message in channel {}.", bannedUser.getUserId(), bannedUser.getServerId(), channelId);
}).exceptionally(throwable -> {
log.error("Failed to ban user {} in guild {} due to a message in channel {}.", bannedUser.getUserId(), bannedUser.getServerId(), channelId, throwable);
return null;
});
}
public CompletableFuture<Void> banForHoneyPotRole(Member targetMember, Role role) {
HoneyPotReasonModel reasonModel = HoneyPotReasonModel
.builder()
.memberDisplay(MemberDisplay.fromMember(targetMember))
@@ -91,7 +112,7 @@ public class HoneyPotServiceBean {
}
private boolean userHasLevel(Member member, Integer level) {
log.info("Checking if member {} is ignored to click on the honeypot in server {}.", member.getIdLong(),member.getGuild().getIdLong());
log.info("Checking if member {} is ignored by the honeypot in server {}.", member.getIdLong(),member.getGuild().getIdLong());
Map<String, Object> parameters = new HashMap<>();
AUserInAServer userInAServer = userInServerManagementService.loadOrCreateUser(member);
parameters.put(LEVEL_CONDITION_USER_ID_PARAMETER, userInAServer.getUserInServerId());

View File

@@ -99,3 +99,14 @@ abstracto.systemConfigs.honeypotIgnoredJoinDurationSeconds.longValue=86400
abstracto.featureFlags.honeypot.featureName=honeypot
abstracto.featureFlags.honeypot.enabled=false
abstracto.featureModes.honeypotRole.featureName=honeypot
abstracto.featureModes.honeypotRole.mode=honeypotRole
abstracto.featureModes.honeypotRole.enabled=false
abstracto.featureModes.honeypotMessage.featureName=honeypot
abstracto.featureModes.honeypotMessage.mode=honeypotMessage
abstracto.featureModes.honeypotMessage.enabled=false
abstracto.systemConfigs.honeypotChannel.name=honeypotChannel
abstracto.systemConfigs.honeypotChannel.longValue=0

View File

@@ -3,7 +3,7 @@
<parent>
<groupId>dev.sheldan.abstracto.modules</groupId>
<artifactId>moderation</artifactId>
<version>1.6.23</version>
<version>1.6.28</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -2,6 +2,8 @@ package dev.sheldan.abstracto.moderation.config.feature;
import dev.sheldan.abstracto.core.config.FeatureConfig;
import dev.sheldan.abstracto.core.config.FeatureDefinition;
import dev.sheldan.abstracto.core.config.FeatureMode;
import dev.sheldan.abstracto.moderation.config.feature.mode.HoneypotMode;
import org.springframework.stereotype.Component;
import java.util.Arrays;
@@ -12,6 +14,7 @@ public class HoneyPotFeatureConfig implements FeatureConfig {
public static final String HONEYPOT_ROLE_ID = "honeypotRoleId";
public static final String HONEYPOT_IGNORED_LEVEL = "honeypotIgnoredLevel";
public static final String HONEYPOT_CHANNEL = "honeypotChannel";
public static final String HONEYPOT_IGNORED_JOIN_DURATION_SECONDS = "honeypotIgnoredJoinDurationSeconds";
@Override
@@ -21,6 +24,11 @@ public class HoneyPotFeatureConfig implements FeatureConfig {
@Override
public List<String> getRequiredSystemConfigKeys() {
return Arrays.asList(HONEYPOT_ROLE_ID, HONEYPOT_IGNORED_LEVEL, HONEYPOT_IGNORED_JOIN_DURATION_SECONDS);
return Arrays.asList(HONEYPOT_ROLE_ID, HONEYPOT_IGNORED_LEVEL, HONEYPOT_IGNORED_JOIN_DURATION_SECONDS, HONEYPOT_CHANNEL);
}
@Override
public List<FeatureMode> getAvailableModes() {
return Arrays.asList(HoneypotMode.values());
}
}

View File

@@ -0,0 +1,16 @@
package dev.sheldan.abstracto.moderation.config.feature.mode;
import dev.sheldan.abstracto.core.config.FeatureMode;
import lombok.Getter;
@Getter
public enum HoneypotMode implements FeatureMode {
ROLE("honeypotRole"),
MESSAGE("honeypotMessage");
private final String key;
HoneypotMode(String key) {
this.key = key;
}
}

View File

@@ -3,7 +3,7 @@
<parent>
<groupId>dev.sheldan.abstracto.modules</groupId>
<artifactId>abstracto-modules</artifactId>
<version>1.6.23</version>
<version>1.6.28</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent>
<groupId>dev.sheldan.abstracto.modules</groupId>
<artifactId>modmail</artifactId>
<version>1.6.23</version>
<version>1.6.28</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -75,7 +75,7 @@ public class ModmailReminderListener implements ModmailThreadActionListener {
log.debug("Thread {} is closed - ignoring.", model.getThreadId());
return ModmailThreadActionListenerResult.IGNORED;
}
Instant timeStampToConsider = getTimestampToUse(thread);
Instant timeStampToConsider = getTimestampToUse(thread, duration);
boolean mustBeReminded = timeInPastDuration.isAfter(timeStampToConsider);
if (mustBeReminded) {
sendReminder(thread)
@@ -97,14 +97,17 @@ public class ModmailReminderListener implements ModmailThreadActionListener {
}
private static Instant getTimestampToUse(ModMailThread thread) {
private static Instant getTimestampToUse(ModMailThread thread, Duration configuredDuration) {
if (thread.getRemindersSnoozedUntil() != null) {
return thread.getRemindersSnoozedUntil();
return thread.getRemindersSnoozedUntil().minus(configuredDuration);
}
return getUpdatedOrCrated(thread);
}
private static Instant getUpdatedOrCrated(ModMailThread thread) {
if(thread.getLastUpdated() != null) {
return thread.getLastUpdated();
}
if(thread.getUpdated() != null) {
return thread.getUpdated();
}

View File

@@ -3,7 +3,7 @@
<parent>
<groupId>dev.sheldan.abstracto.modules</groupId>
<artifactId>modmail</artifactId>
<version>1.6.23</version>
<version>1.6.28</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent>
<groupId>dev.sheldan.abstracto.modules</groupId>
<artifactId>abstracto-modules</artifactId>
<version>1.6.23</version>
<version>1.6.28</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent>
<groupId>dev.sheldan.abstracto</groupId>
<artifactId>abstracto-application</artifactId>
<version>1.6.23</version>
<version>1.6.28</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent>
<artifactId>abstracto-modules</artifactId>
<groupId>dev.sheldan.abstracto.modules</groupId>
<version>1.6.23</version>
<version>1.6.28</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent>
<artifactId>profanity-filter</artifactId>
<groupId>dev.sheldan.abstracto.modules</groupId>
<version>1.6.23</version>
<version>1.6.28</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent>
<groupId>dev.sheldan.abstracto.modules</groupId>
<artifactId>profanity-filter</artifactId>
<version>1.6.23</version>
<version>1.6.28</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent>
<artifactId>abstracto-modules</artifactId>
<groupId>dev.sheldan.abstracto.modules</groupId>
<version>1.6.23</version>
<version>1.6.28</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent>
<artifactId>remind</artifactId>
<groupId>dev.sheldan.abstracto.modules</groupId>
<version>1.6.23</version>
<version>1.6.28</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent>
<artifactId>remind</artifactId>
<groupId>dev.sheldan.abstracto.modules</groupId>
<version>1.6.23</version>
<version>1.6.28</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent>
<artifactId>abstracto-modules</artifactId>
<groupId>dev.sheldan.abstracto.modules</groupId>
<version>1.6.23</version>
<version>1.6.28</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent>
<artifactId>repost-detection</artifactId>
<groupId>dev.sheldan.abstracto.modules</groupId>
<version>1.6.23</version>
<version>1.6.28</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent>
<artifactId>repost-detection</artifactId>
<groupId>dev.sheldan.abstracto.modules</groupId>
<version>1.6.23</version>
<version>1.6.28</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent>
<artifactId>abstracto-modules</artifactId>
<groupId>dev.sheldan.abstracto.modules</groupId>
<version>1.6.23</version>
<version>1.6.28</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent>
<artifactId>starboard</artifactId>
<groupId>dev.sheldan.abstracto.modules</groupId>
<version>1.6.23</version>
<version>1.6.28</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent>
<artifactId>starboard</artifactId>
<groupId>dev.sheldan.abstracto.modules</groupId>
<version>1.6.23</version>
<version>1.6.28</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent>
<groupId>dev.sheldan.abstracto.modules</groupId>
<artifactId>abstracto-modules</artifactId>
<version>1.6.23</version>
<version>1.6.28</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent>
<groupId>dev.sheldan.abstracto.modules</groupId>
<artifactId>statistic</artifactId>
<version>1.6.23</version>
<version>1.6.28</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent>
<groupId>dev.sheldan.abstracto.modules</groupId>
<artifactId>statistic</artifactId>
<version>1.6.23</version>
<version>1.6.28</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent>
<artifactId>abstracto-modules</artifactId>
<groupId>dev.sheldan.abstracto.modules</groupId>
<version>1.6.23</version>
<version>1.6.28</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -4,7 +4,7 @@
<parent>
<groupId>dev.sheldan.abstracto.modules</groupId>
<artifactId>sticky-roles</artifactId>
<version>1.6.23</version>
<version>1.6.28</version>
</parent>
<artifactId>sticky-roles-impl</artifactId>

View File

@@ -4,7 +4,7 @@
<parent>
<groupId>dev.sheldan.abstracto.modules</groupId>
<artifactId>sticky-roles</artifactId>
<version>1.6.23</version>
<version>1.6.28</version>
</parent>
<artifactId>sticky-roles-int</artifactId>

View File

@@ -3,7 +3,7 @@
<parent>
<artifactId>abstracto-modules</artifactId>
<groupId>dev.sheldan.abstracto.modules</groupId>
<version>1.6.23</version>
<version>1.6.28</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent>
<artifactId>suggestion</artifactId>
<groupId>dev.sheldan.abstracto.modules</groupId>
<version>1.6.23</version>
<version>1.6.28</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent>
<artifactId>suggestion</artifactId>
<groupId>dev.sheldan.abstracto.modules</groupId>
<version>1.6.23</version>
<version>1.6.28</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent>
<artifactId>abstracto-modules</artifactId>
<groupId>dev.sheldan.abstracto.modules</groupId>
<version>1.6.23</version>
<version>1.6.28</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent>
<artifactId>twitch</artifactId>
<groupId>dev.sheldan.abstracto.modules</groupId>
<version>1.6.23</version>
<version>1.6.28</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -13,6 +13,7 @@ import dev.sheldan.abstracto.core.service.management.UserInServerManagementServi
import dev.sheldan.abstracto.core.templating.model.MessageToSend;
import dev.sheldan.abstracto.core.templating.service.TemplateService;
import dev.sheldan.abstracto.core.utils.CompletableFutureList;
import dev.sheldan.abstracto.core.utils.ParseUtils;
import dev.sheldan.abstracto.twitch.config.TwitchFeatureConfig;
import dev.sheldan.abstracto.twitch.config.TwitchFeatureDefinition;
import dev.sheldan.abstracto.twitch.config.TwitchFeatureMode;
@@ -26,6 +27,8 @@ import dev.sheldan.abstracto.twitch.model.template.*;
import dev.sheldan.abstracto.twitch.service.management.StreamSessionManagementService;
import dev.sheldan.abstracto.twitch.service.management.StreamSessionSectionManagementService;
import dev.sheldan.abstracto.twitch.service.management.StreamerManagementService;
import java.time.Duration;
import java.time.Instant;
import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.Member;
@@ -92,6 +95,9 @@ public class StreamerServiceBean implements StreamerService {
@Autowired
private MessageService messageService;
@Autowired
private ConfigService configService;
@Autowired
private StreamerServiceBean self;
@@ -168,6 +174,7 @@ public class StreamerServiceBean implements StreamerService {
.getCurrentSession()
.getSections()
.stream()
.filter(pastSection -> !pastSection.getTitle().equals(stream.getTitle()) && !pastSection.getGameId().equals(stream.getGameId())) // filter out the current section in case it was refreshed
.sorted(Comparator.comparing(StreamSessionSection::getId).reversed())
.map(StreamSectionDisplay::fromSection)
.toList();
@@ -277,6 +284,8 @@ public class StreamerServiceBean implements StreamerService {
log.debug("Searching through {} servers for twitch notifications and {} have twitch feature enabled.", servers.size(), serversWithEnabledFeature.size());
serversWithEnabledFeature.forEach(server -> {
List<Streamer> streamersInServer = streamerManagementService.getStreamersForServer(server);
String refreshDurationString = configService.getStringValueOrConfigDefault(TwitchFeatureConfig.TWITCH_REFRESH_INTERVAL, server.getId());
Duration refreshDuration = ParseUtils.parseDuration(refreshDurationString);
Map<Long, Streamer> streamerIdMap = streamersInServer
.stream()
.collect(Collectors.toMap(Streamer::getId, Function.identity()));
@@ -295,7 +304,7 @@ public class StreamerServiceBean implements StreamerService {
List<Stream> streamsOfUsers = twitchService.getStreamsByUserIds(userIds);
Set<Long> onlineStreamers = new HashSet<>();
Map<Long, Boolean> updateNotificationFlagValues = new HashMap<>();
streamsOfUsers.forEach(stream -> self.processOnlineStreamer(server, streamerMap, onlineStreamers, updateNotificationFlagValues, stream));
streamsOfUsers.forEach(stream -> self.processOnlineStreamer(server, streamerMap, onlineStreamers, updateNotificationFlagValues, stream, refreshDuration));
Set<Long> allStreamersInServer = streamerIdMap.keySet();
allStreamersInServer.removeAll(onlineStreamers); // then we have those that went offline
Map<Long, Boolean> deleteFlagValues = new HashMap<>();
@@ -370,7 +379,8 @@ public class StreamerServiceBean implements StreamerService {
}
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void processOnlineStreamer(AServer server, Map<String, Streamer> streamerMap, Set<Long> onlineStreamers, Map<Long, Boolean> updateNotificationFlagValues, Stream stream) {
public void processOnlineStreamer(AServer server, Map<String, Streamer> streamerMap, Set<Long> onlineStreamers, Map<Long, Boolean> updateNotificationFlagValues,
Stream stream, Duration refreshDuration) {
Streamer streamer = streamerMap.get(stream.getUserId());
Long streamerId = streamer.getId();
onlineStreamers.add(streamerId);
@@ -378,18 +388,19 @@ public class StreamerServiceBean implements StreamerService {
// that is the case if you add an online streamer
User streamerUser = twitchService.getStreamerById(stream.getUserId());
StreamSession currentSession = streamer.getCurrentSession();
Long serverId = streamer.getServer().getId();
if (Boolean.TRUE.equals(streamer.getOnline()) && currentSession != null) {
// we already know that this streamer is online
log.debug("Not notifying for streamer {} in server {} - streamer is already online.", streamerId, server.getId());
if(!stream.getGameId().equals(streamer.getCurrentGameId())) {
log.info("Streamer {} changed game from {} to {} - storing new section.", streamerId, streamer.getCurrentGameId(), stream.getGameId());
streamSessionSectionService.createSectionFromStream(currentSession, stream);
currentSession.setLastUpdated(Instant.now());
if (updateNotificationFlagValues.computeIfAbsent(streamer.getServer().getId(),
aLong -> featureModeService.featureModeActive(TwitchFeatureDefinition.TWITCH, aLong, TwitchFeatureMode.UPDATE_NOTIFICATION))) {
log.info("Updating notification is enabled - updating notification for streamer {}.", streamer.getId());
Long notificationMessageId = currentSession.getId();
Long notificationChannelId = currentSession.getChannel().getId();
Long serverId = streamer.getServer().getId();
updateExistingNotification(stream, streamer, streamerUser).thenAccept(unused -> {
log.info("Updating existing notification {} for server {} in channel {} about streamer {}.",
notificationMessageId, serverId, notificationChannelId, streamerId);
@@ -400,6 +411,20 @@ public class StreamerServiceBean implements StreamerService {
});
}
streamer.setCurrentGameId(stream.getGameId());
} else if(currentSession.getLastUpdated().isBefore(Instant.now().minus(refreshDuration)) &&
updateNotificationFlagValues.computeIfAbsent(streamer.getServer().getId(),
serverIdKey -> featureModeService.featureModeActive(TwitchFeatureDefinition.TWITCH, serverIdKey, TwitchFeatureMode.UPDATE_NOTIFICATION))) {
Long notificationMessageId = currentSession.getId();
currentSession.setLastUpdated(Instant.now());
Long notificationChannelId = currentSession.getChannel().getId();
updateExistingNotification(stream, streamer, streamerUser).thenAccept(unused -> {
log.info("Updating existing notification {} for server {} in channel {} about streamer {}.",
notificationMessageId, serverId, notificationChannelId, streamerId);
}).exceptionally(throwable -> {
log.error("Failed to update existing notification {} for server {} in channel {} about streamer {}.",
notificationMessageId, serverId, notificationChannelId, streamerId, throwable);
return null;
});
}
} else if(currentSession == null &&
!postTargetService.postTargetUsableInServer(TwitchPostTarget.TWITCH_LIVE_NOTIFICATION, server.getId())) {

View File

@@ -6,6 +6,7 @@ import dev.sheldan.abstracto.core.service.management.ChannelManagementService;
import dev.sheldan.abstracto.twitch.model.database.Streamer;
import dev.sheldan.abstracto.twitch.model.database.StreamSession;
import dev.sheldan.abstracto.twitch.repository.StreamSessionRepository;
import java.time.Instant;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@@ -26,6 +27,7 @@ public class StreamSessionManagementServiceBean implements StreamSessionManageme
.id(messageId)
.startTime(stream.getStartedAtInstant())
.channel(channel)
.lastUpdated(Instant.now())
.streamer(streamer)
.streamId(stream.getId())
.build();

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="tables/tables.xml" relativeToChangelogFile="true"/>
</databaseChangeLog>

View File

@@ -0,0 +1,12 @@
<?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="stream_session-add_last_updated">
<addColumn tableName="stream_session">
<column name="last_updated" type="TIMESTAMP WITHOUT TIME ZONE" defaultValueComputed="CURRENT_TIMESTAMP">
<constraints nullable="false" />
</column>
</addColumn>
</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="stream_session.xml" relativeToChangelogFile="true"/>
</databaseChangeLog>

View File

@@ -3,4 +3,5 @@
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="1.4.27/collection.xml" relativeToChangelogFile="true"/>
<include file="1.6.25/collection.xml" relativeToChangelogFile="true"/>
</databaseChangeLog>

View File

@@ -12,4 +12,7 @@ abstracto.featureModes.deleteNotification.enabled=true
abstracto.featureModes.updateNotification.featureName=twitch
abstracto.featureModes.updateNotification.mode=updateNotification
abstracto.featureModes.updateNotification.enabled=true
abstracto.featureModes.updateNotification.enabled=true
abstracto.systemConfigs.twitchRefreshInterval.name=twitchRefreshInterval
abstracto.systemConfigs.twitchRefreshInterval.stringValue=30m

View File

@@ -3,7 +3,7 @@
<parent>
<groupId>dev.sheldan.abstracto.modules</groupId>
<artifactId>twitch</artifactId>
<version>1.6.23</version>
<version>1.6.28</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -11,6 +11,9 @@ import java.util.List;
@Component
public class TwitchFeatureConfig implements FeatureConfig {
public static final String TWITCH_REFRESH_INTERVAL = "twitchRefreshInterval";
@Override
public FeatureDefinition getFeature() {
return TwitchFeatureDefinition.TWITCH;
@@ -25,4 +28,9 @@ public class TwitchFeatureConfig implements FeatureConfig {
public List<FeatureMode> getAvailableModes() {
return Arrays.asList(TwitchFeatureMode.DELETE_NOTIFICATION, TwitchFeatureMode.UPDATE_NOTIFICATION);
}
@Override
public List<String> getRequiredSystemConfigKeys() {
return List.of(TWITCH_REFRESH_INTERVAL);
}
}

View File

@@ -39,6 +39,9 @@ public class StreamSession {
@Column(name = "updated", insertable = false, updatable = false)
private Instant updated;
@Column(name = "lastUpdated")
private Instant lastUpdated;
@Column(name = "startTime", nullable = false)
private Instant startTime;

View File

@@ -3,7 +3,7 @@
<parent>
<groupId>dev.sheldan.abstracto.modules</groupId>
<artifactId>abstracto-modules</artifactId>
<version>1.6.23</version>
<version>1.6.28</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent>
<groupId>dev.sheldan.abstracto.modules</groupId>
<artifactId>utility</artifactId>
<version>1.6.23</version>
<version>1.6.28</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent>
<groupId>dev.sheldan.abstracto.modules</groupId>
<artifactId>utility</artifactId>
<version>1.6.23</version>
<version>1.6.28</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent>
<artifactId>abstracto-modules</artifactId>
<groupId>dev.sheldan.abstracto.modules</groupId>
<version>1.6.23</version>
<version>1.6.28</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent>
<groupId>dev.sheldan.abstracto.modules</groupId>
<artifactId>voice-channel-context</artifactId>
<version>1.6.23</version>
<version>1.6.28</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent>
<groupId>dev.sheldan.abstracto.modules</groupId>
<artifactId>voice-channel-context</artifactId>
<version>1.6.23</version>
<version>1.6.28</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent>
<groupId>dev.sheldan.abstracto.modules</groupId>
<artifactId>abstracto-modules</artifactId>
<version>1.6.23</version>
<version>1.6.28</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent>
<groupId>dev.sheldan.abstracto.modules</groupId>
<artifactId>webservices</artifactId>
<version>1.6.23</version>
<version>1.6.28</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent>
<groupId>dev.sheldan.abstracto.modules</groupId>
<artifactId>webservices</artifactId>
<version>1.6.23</version>
<version>1.6.28</version>
</parent>
<modelVersion>4.0.0</modelVersion>

Some files were not shown because too many files have changed in this diff Show More