[OPB-17] implementing setups functionality

This commit is contained in:
Sheldan
2021-05-11 13:05:17 +02:00
parent 798d7bc894
commit 67ae9702fd
26 changed files with 1808 additions and 2 deletions

View File

@@ -122,6 +122,12 @@
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>dev.sheldan.oneplus.bot.application.modules</groupId>
<artifactId>setups</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</project>

View File

@@ -12,6 +12,7 @@
<packaging>pom</packaging>
<modules>
<module>news</module>
<module>setups</module>
</modules>
<properties>

View File

@@ -0,0 +1,36 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>oneplus-bot-modules</artifactId>
<groupId>dev.sheldan.oneplus.bot.application.modules</groupId>
<version>1.3.11-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>setups</artifactId>
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<descriptors>
<descriptor>src/main/assembly/liquibase.xml</descriptor>
</descriptors>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@@ -0,0 +1,18 @@
<assembly xmlns="http://maven.apache.org/ASSEMBLY/2.1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.1.0 http://maven.apache.org/xsd/assembly-2.1.0.xsd">
<id>liquibase</id>
<formats>
<format>zip</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<fileSets>
<fileSet>
<outputDirectory>.</outputDirectory>
<directory>${project.basedir}/src/main/resources/migrations</directory>
<includes>
<include>**/*</include>
</includes>
</fileSet>
</fileSets>
</assembly>

View File

@@ -0,0 +1,15 @@
package dev.sheldan.oneplus.bot.modules.setups.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
@Configuration
public class SetupsBeanConfig {
@Bean(value = "setupsDelayedExecutor")
public ScheduledExecutorService getDelayedExecutor() {
return Executors.newSingleThreadScheduledExecutor();
}
}

View File

@@ -0,0 +1,30 @@
package dev.sheldan.oneplus.bot.modules.setups.config;
import dev.sheldan.abstracto.core.config.FeatureConfig;
import dev.sheldan.abstracto.core.config.FeatureDefinition;
import dev.sheldan.abstracto.core.config.PostTargetEnum;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.List;
import static dev.sheldan.oneplus.bot.modules.setups.listener.SetupsListener.SETUPS_UPVOTE_EMOTE_KEY;
@Component
public class SetupsFeature implements FeatureConfig {
@Override
public FeatureDefinition getFeature() {
return SetupsFeatureDefinition.SETUPS;
}
@Override
public List<PostTargetEnum> getRequiredPostTargets() {
return Arrays.asList(SetupsPostTarget.SETUPS);
}
@Override
public List<String> getRequiredEmotes() {
return Arrays.asList(SETUPS_UPVOTE_EMOTE_KEY);
}
}

View File

@@ -0,0 +1,15 @@
package dev.sheldan.oneplus.bot.modules.setups.config;
import dev.sheldan.abstracto.core.config.FeatureDefinition;
import lombok.Getter;
@Getter
public enum SetupsFeatureDefinition implements FeatureDefinition {
SETUPS("setups");
private String key;
SetupsFeatureDefinition(String key) {
this.key = key;
}
}

View File

@@ -0,0 +1,15 @@
package dev.sheldan.oneplus.bot.modules.setups.config;
import dev.sheldan.abstracto.core.config.PostTargetEnum;
import lombok.Getter;
@Getter
public enum SetupsPostTarget implements PostTargetEnum {
SETUPS("setups");
private String key;
SetupsPostTarget(String key) {
this.key = key;
}
}

View File

@@ -0,0 +1,10 @@
package dev.sheldan.oneplus.bot.modules.setups.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
@Configuration
@PropertySource("classpath:setups.properties")
public class SetupsProperties {
}

View File

@@ -0,0 +1,95 @@
package dev.sheldan.oneplus.bot.modules.setups.listener;
import dev.sheldan.abstracto.core.config.FeatureDefinition;
import dev.sheldan.abstracto.core.listener.DefaultListenerResult;
import dev.sheldan.abstracto.core.listener.async.jda.AsyncMessageReceivedListener;
import dev.sheldan.abstracto.core.models.database.PostTarget;
import dev.sheldan.abstracto.core.models.listener.MessageReceivedModel;
import dev.sheldan.abstracto.core.service.MessageService;
import dev.sheldan.abstracto.core.service.ReactionService;
import dev.sheldan.abstracto.core.service.management.PostTargetManagement;
import dev.sheldan.oneplus.bot.modules.setups.config.SetupsFeatureDefinition;
import dev.sheldan.oneplus.bot.modules.setups.config.SetupsPostTarget;
import dev.sheldan.oneplus.bot.modules.setups.service.SetupsService;
import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.entities.Message;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.util.Optional;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
@Component
@Slf4j
public class SetupsListener implements AsyncMessageReceivedListener {
@Autowired
private PostTargetManagement postTargetManagement;
@Autowired
private SetupsService setupsService;
@Qualifier("setupsDelayedExecutor")
@Autowired
private ScheduledExecutorService scheduledExecutorService;
@Value("${abstracto.setups.deletionDelaySeconds}")
private Long deletionDelay;
@Autowired
private MessageService messageService;
@Autowired
private ReactionService reactionService;
public static final String SETUPS_UPVOTE_EMOTE_KEY = "setupsUpvote";
@Override
public DefaultListenerResult execute(MessageReceivedModel model) {
Optional<PostTarget> setupsPostTargetOptional = postTargetManagement.getPostTargetOptional(SetupsPostTarget.SETUPS, model.getServerId());
if(setupsPostTargetOptional.isPresent()) {
PostTarget setupsTarget = setupsPostTargetOptional.get();
Message originalMessage = model.getMessage();
if(originalMessage.getChannel().getIdLong() == setupsTarget.getChannelReference().getId()) {
Long serverId = model.getServerId();
boolean currentlyInvalid = setupsService.currentlyInvalid(originalMessage);
if(currentlyInvalid) {
if(setupsService.mightContainEmbed(originalMessage)) {
log.info("Setup message did not contain embeds not attachments, but a link - waiting for embeds on message {}" +
" in channel {} in guild {} by user {}.", originalMessage.getIdLong(), originalMessage.getChannel().getIdLong(),
originalMessage.getGuild().getIdLong(), originalMessage.getAuthor().getIdLong());
scheduledExecutorService.schedule(() -> {
messageService.loadMessage(originalMessage).thenAccept(loadedMessage -> {
if(setupsService.currentlyInvalid(loadedMessage)) {
log.info("Message did not contain attachments nor embeds after a delay - deleting setups message {}.", loadedMessage.getIdLong());
messageService.deleteMessage(loadedMessage);
} else {
log.info("Message contained embeds/attachments after a delay - message was accepted {}.", loadedMessage.getIdLong());
reactionService.addReactionToMessage(SETUPS_UPVOTE_EMOTE_KEY, serverId, loadedMessage);
}
});
}, deletionDelay, TimeUnit.SECONDS);
} else {
log.info("Did not find any attachments nor embeds and no link to lead to any embeds - deleting setup message {} in channel {} in server {}" +
"by user {} for setups.", originalMessage.getIdLong(), originalMessage.getChannel().getIdLong(), originalMessage.getGuild().getIdLong(),
originalMessage.getAuthor().getIdLong());
messageService.deleteMessage(originalMessage);
}
} else {
log.info("Accepting setups message {} in channel {} in guild {} from user {}.", originalMessage.getIdLong(),
originalMessage.getChannel().getIdLong(), originalMessage.getGuild().getIdLong(), originalMessage.getAuthor().getIdLong());
reactionService.addReactionToMessage(SETUPS_UPVOTE_EMOTE_KEY, serverId, originalMessage);
}
}
}
return DefaultListenerResult.IGNORED;
}
@Override
public FeatureDefinition getFeature() {
return SetupsFeatureDefinition.SETUPS;
}
}

View File

@@ -0,0 +1,35 @@
package dev.sheldan.oneplus.bot.modules.setups.service;
import net.dv8tion.jda.api.entities.EmbedType;
import net.dv8tion.jda.api.entities.Message;
import org.springframework.stereotype.Component;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@Component
public class SetupsService {
private static final Pattern URL_REGEX = Pattern.compile("((https?|ftp)://|(www|ftp)\\.)?[a-z0-9-]+(\\.[a-z0-9-]+)+([/?].*)?");
public boolean mightContainEmbed(Message message) {
Matcher urlMatcher = URL_REGEX.matcher(message.getContentRaw());
return urlMatcher.find();
}
public boolean currentlyValid(Message message) {
return !message.getAttachments().isEmpty() ||
(
!message.getEmbeds().isEmpty() &&
message
.getEmbeds()
.stream()
.anyMatch(messageEmbed -> messageEmbed.getType().equals(EmbedType.IMAGE))
);
}
public boolean currentlyInvalid(Message message) {
return !currentlyValid(message);
}
}

View File

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

View File

@@ -0,0 +1,11 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog dbchangelog.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog.xsd
http://www.liquibase.org/xml/ns/pro dbchangelog.xsd" >
<include file="feature.xml" relativeToChangelogFile="true"/>
<include file="default_emote.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:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog dbchangelog.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog.xsd
http://www.liquibase.org/xml/ns/pro dbchangelog.xsd" >
<changeSet author="Sheldan" id="setups_default_emote-insert">
<insert tableName="default_emote">
<column name="emote_key" value="setupsUpvote"/>
<column name="name" value="👍"/>
</insert>
</changeSet>
</databaseChangeLog>

View File

@@ -0,0 +1,14 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog dbchangelog.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog.xsd
http://www.liquibase.org/xml/ns/pro dbchangelog.xsd" >
<changeSet author="Sheldan" id="setups_feature-insertion">
<insert tableName="feature">
<column name="key" value="setups"/>
</insert>
</changeSet>
</databaseChangeLog>

View File

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

View File

@@ -0,0 +1,6 @@
abstracto.postTargets.setups.name=setups
abstracto.featureFlags.setups.featureName=setups
abstracto.featureFlags.setups.enabled=false
abstracto.setups.deletionDelaySeconds=3

View File

@@ -287,6 +287,16 @@
<destFileName>news.zip</destFileName>
</artifactItem>
<artifactItem>
<groupId>dev.sheldan.oneplus.bot.templates.translations</groupId>
<artifactId>setups-translations</artifactId>
<version>${project.version}</version>
<type>zip</type>
<overWrite>true</overWrite>
<outputDirectory>${file.basedir}/deployment/translation-artifacts/</outputDirectory>
<destFileName>setups.zip</destFileName>
</artifactItem>
<!-- liquibase artifacts -->
<artifactItem>
<groupId>dev.sheldan.abstracto.scheduling</groupId>
@@ -444,6 +454,17 @@
<destFileName>news.zip</destFileName>
</artifactItem>
<artifactItem>
<groupId>dev.sheldan.oneplus.bot.application.modules</groupId>
<artifactId>setups</artifactId>
<version>${project.version}</version>
<classifier>liquibase</classifier>
<type>zip</type>
<overWrite>true</overWrite>
<outputDirectory>${file.basedir}/deployment/liquibase-artifacts/</outputDirectory>
<destFileName>setups.zip</destFileName>
</artifactItem>
<!-- overrides -->
<artifactItem>

View File

@@ -7,7 +7,7 @@
"translation_artifacts": ["utility", "core", "entertainment", "starboard", "link-embed", "webservices", "suggestion",
"remind", "logging", "invite-filter",
"starboard-custom",
"news"],
"news", "setups"],
"liquibase_artifacts": [
{ "zip": "scheduling", "file": "scheduling-changeLog.xml" },
{ "zip": "core", "file": "core-changeLog.xml" },
@@ -20,6 +20,7 @@
{ "zip": "logging", "file": "logging-changeLog.xml"},
{ "zip": "suggestion", "file": "suggestion-changeLog.xml"},
{ "zip": "invite-filter", "file": "inviteFilter-changeLog.xml"},
{ "zip": "setups", "file": "setups-changeLog.xml"},
{ "zip": "starboard-custom", "file": "starboard-custom-changeLog.xml"},
{ "zip": "news", "file": "news-changeLog.xml"}
]

View File

@@ -21,7 +21,7 @@
<goal>single</goal>
</goals>
<configuration>
<finalName>starboard-custom-templates-${project.version}</finalName>
<finalName>news-templates-${project.version}</finalName>
<appendAssemblyId>false</appendAssemblyId>
<descriptors>
<descriptor>src/main/assembly/assembly.xml</descriptor>

View File

@@ -13,5 +13,6 @@
<modules>
<module>starboard-custom-translations</module>
<module>news-translations</module>
<module>setups-translations</module>
</modules>
</project>

View File

@@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>translations</artifactId>
<groupId>dev.sheldan.oneplus.bot.templates.translations</groupId>
<version>1.3.11-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>setups-translations</artifactId>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<finalName>setups-translations-${project.version}</finalName>
<appendAssemblyId>false</appendAssemblyId>
<descriptors>
<descriptor>src/main/assembly/assembly.xml</descriptor>
</descriptors>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@@ -0,0 +1,15 @@
<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
<id>zip</id>
<includeBaseDirectory>false</includeBaseDirectory>
<formats>
<format>zip</format>
</formats>
<fileSets>
<fileSet>
<outputDirectory>.</outputDirectory>
<directory>${project.basedir}/src/main/resources</directory>
</fileSet>
</fileSets>
</assembly>

View File

@@ -0,0 +1 @@
The channel which should be scanned for setups. Currently: ${currentTarget}