[OPB-19] adding referral link functionality

changing name for setups feature
aligning starboard custom module name
This commit is contained in:
Sheldan
2021-05-12 00:14:18 +02:00
parent 67ae9702fd
commit e236522328
75 changed files with 2302 additions and 98 deletions

View File

@@ -0,0 +1,41 @@
<?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>
<groupId>dev.sheldan.oneplus.bot.application.modules</groupId>
<artifactId>oneplus-bot-modules</artifactId>
<version>1.3.11-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>referral</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<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.referral.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 ReferralBeanConfig {
@Bean(value = "referralDelayExecutor")
public ScheduledExecutorService getDelayedExecutor() {
return Executors.newSingleThreadScheduledExecutor();
}
}

View File

@@ -0,0 +1,24 @@
package dev.sheldan.oneplus.bot.modules.referral.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;
@Component
public class ReferralFeature implements FeatureConfig {
@Override
public FeatureDefinition getFeature() {
return ReferralFeatureDefinition.REFERRAL;
}
@Override
public List<PostTargetEnum> getRequiredPostTargets() {
return Arrays.asList(ReferralPostTarget.REFERRAL);
}
}

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,167 @@
package dev.sheldan.oneplus.bot.modules.referral.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.ServerUser;
import dev.sheldan.abstracto.core.models.database.PostTarget;
import dev.sheldan.abstracto.core.models.listener.MessageReceivedModel;
import dev.sheldan.abstracto.core.service.ChannelService;
import dev.sheldan.abstracto.core.service.MessageService;
import dev.sheldan.abstracto.core.service.management.PostTargetManagement;
import dev.sheldan.abstracto.core.utils.CompletableFutureList;
import dev.sheldan.oneplus.bot.modules.referral.config.ReferralFeatureDefinition;
import dev.sheldan.oneplus.bot.modules.referral.config.ReferralPostTarget;
import dev.sheldan.oneplus.bot.modules.referral.model.template.Referral;
import dev.sheldan.oneplus.bot.modules.referral.model.template.ReferralPostModel;
import dev.sheldan.oneplus.bot.modules.referral.model.template.ReferralTooRecentModel;
import dev.sheldan.oneplus.bot.modules.referral.service.ReferralServiceBean;
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 org.springframework.transaction.annotation.Transactional;
import java.time.Instant;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
@Component
@Slf4j
public class ReferralListener implements AsyncMessageReceivedListener {
@Autowired
private PostTargetManagement postTargetManagement;
@Autowired
private MessageService messageService;
@Autowired
private ReferralServiceBean referralServiceBean;
@Autowired
private ChannelService channelService;
@Autowired
private ReferralListener self;
@Qualifier("referralDelayExecutor")
@Autowired
private ScheduledExecutorService scheduledExecutorService;
@Value("${oneplus.bot.referral.deleteDelaySeconds}")
private Long deleteDelaySeconds;
@Value("${oneplus.bot.referral.maxReferralCount}")
private Long maxReferralLinksPerPost;
private static final String NO_REFERRAL_LINK_FOUND_TEMPLATE_KEY = "referralListener_no_referral_link_found";
private static final String REFERRAL_POST_TOO_RECENT_TEMPLATE_KEY = "referralListener_too_recent_post";
private static final String REFERRAL_POST_EMBED_TEMPLATE_KEY = "referralListener_referral_post";
@Override
public DefaultListenerResult execute(MessageReceivedModel model) {
Long serverId = model.getServerId();
Optional<PostTarget> referralPostTargetOptional = postTargetManagement.getPostTargetOptional(ReferralPostTarget.REFERRAL, serverId);
if(referralPostTargetOptional.isPresent()) {
PostTarget referralTarget = referralPostTargetOptional.get();
Message message = model.getMessage();
if (message.getChannel().getIdLong() == referralTarget.getChannelReference().getId()) {
Long authorId = message.getAuthor().getIdLong();
if (!message.isFromGuild() || message.isWebhookMessage() || message.getType().isSystem()) {
log.info("Deleting illegal message by user {} in referral channel in server {}.", authorId, serverId);
messageService.deleteMessage(message).exceptionally(deletionErrorConsumer(message));
return DefaultListenerResult.IGNORED;
}
if(message.getAuthor().isBot()) {
log.debug("Ignoring message from a bot user {} in referral channel in server {}.", authorId, serverId);
return DefaultListenerResult.IGNORED;
}
List<Referral> foundReferrals = referralServiceBean.getReferralsFromMessage(message);
if(foundReferrals.isEmpty()) {
log.info("Did not find referrals in message {} by user {} in server {} - deleting message.",
message.getIdLong(), authorId, serverId);
deleteAndNotify(message, NO_REFERRAL_LINK_FOUND_TEMPLATE_KEY, new Object());
return DefaultListenerResult.IGNORED;
}
log.info("Found {} referral links in message {} by user {} in server {}.",
foundReferrals.size(), message.getIdLong(), authorId, serverId);
Instant nextReferralDate = referralServiceBean.getNextReferralDate(message.getMember());
if(nextReferralDate.isAfter(Instant.now())) {
log.info("Referrals in message {} by user {} in server {} was before allowed repost date {} - deleting message.",
message.getIdLong(), authorId, serverId, nextReferralDate);
ReferralTooRecentModel templateModel = ReferralTooRecentModel
.builder()
.nextReferralDate(nextReferralDate)
.build();
deleteAndNotify(message, REFERRAL_POST_TOO_RECENT_TEMPLATE_KEY, templateModel);
return DefaultListenerResult.PROCESSED;
}
if(foundReferrals.size() > maxReferralLinksPerPost) {
log.info("More referral links ({}) than allowed ({}) in message {} in server {} by user {}.",
foundReferrals.size(), maxReferralLinksPerPost, message.getIdLong(), serverId, authorId);
foundReferrals = foundReferrals.subList(0, maxReferralLinksPerPost.intValue());
}
ReferralPostModel postModel = ReferralPostModel
.builder()
.referrals(foundReferrals)
.postingMember(message.getMember())
.build();
ServerUser serverUser = ServerUser.fromMember(message.getMember());
CompletableFutureList<Message> sendFutures = new CompletableFutureList<>(channelService
.sendEmbedTemplateInMessageChannelList(REFERRAL_POST_EMBED_TEMPLATE_KEY, postModel, message.getChannel()));
CompletableFuture<Void> deletionFuture = messageService.deleteMessage(message);
CompletableFuture.allOf(sendFutures.getMainFuture(), deletionFuture)
.thenAccept(unused -> self.updateReferralStateInDatabase(serverUser))
.exceptionally(throwable -> {
log.error("Failed to delete or persist referral message from user {} in server {}.", authorId, serverId, throwable);
return null;
});
}
}
return DefaultListenerResult.IGNORED;
}
@Transactional
public void updateReferralStateInDatabase(ServerUser serverUser) {
referralServiceBean.updateDbState(serverUser);
}
private void deleteAndNotify(Message message, String usedTemplate, Object usedModel) {
CompletableFutureList<Message> futures = new CompletableFutureList<>(channelService
.sendEmbedTemplateInMessageChannelList(usedTemplate, usedModel, message.getChannel()));
futures.getMainFuture().thenAccept(unused ->
scheduledExecutorService.schedule(() ->
futures.getObjects().forEach(createdMessage -> messageService.deleteMessage(createdMessage)),
deleteDelaySeconds, TimeUnit.SECONDS));
futures.getMainFuture().exceptionally(throwable -> {
log.error("Failed to send denial about setups with template {} message {} in channel {} in server {} by {}.",
usedTemplate, message.getIdLong(), message.getChannel().getIdLong(), message.getGuild().getIdLong(), message.getAuthor().getIdLong());
return null;
});
messageService.deleteMessage(message).exceptionally(deletionErrorConsumer(message));
}
private Function<Throwable, Void> deletionErrorConsumer(Message message) {
return throwable -> {
log.error("Failed to delete setups message {} in channel {} in server {} by {}.",
message.getIdLong(), message.getChannel().getIdLong(), message.getGuild().getIdLong(), message.getAuthor().getIdLong());
return null;
};
}
@Override
public FeatureDefinition getFeature() {
return ReferralFeatureDefinition.REFERRAL;
}
}

View File

@@ -0,0 +1,14 @@
package dev.sheldan.oneplus.bot.modules.referral.model;
import lombok.Getter;
@Getter
public enum ReferralType {
SMARTPHONE("smartphone"), ACCESSORIES("accessories"), SMARTPHONE_INDIA("smartphoneIndia");
private String key;
ReferralType(String key) {
this.key = key;
}
}

View File

@@ -0,0 +1,44 @@
package dev.sheldan.oneplus.bot.modules.referral.model.database;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
import lombok.*;
import javax.persistence.*;
import java.time.Instant;
@Builder
@Entity
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "referral_user_in_server")
@Getter
@Setter
@EqualsAndHashCode
public class ReferralUserInAServer {
@Id
@Column(name = "id")
private Long id;
/**
* The {@link AUserInAServer user} which is represented by this object
*/
@OneToOne(fetch = FetchType.LAZY, cascade = {CascadeType.PERSIST, CascadeType.MERGE})
@PrimaryKeyJoinColumn
private AUserInAServer user;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "server_id", nullable = false)
private AServer server;
@Column(name = "last_referral_post")
private Instant lastReferralPost;
@Column(name = "created")
private Instant created;
@Column(name = "updated")
private Instant updated;
}

View File

@@ -0,0 +1,15 @@
package dev.sheldan.oneplus.bot.modules.referral.model.template;
import dev.sheldan.oneplus.bot.modules.referral.model.ReferralType;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
@Builder
public class Referral {
private String referralLink;
private String referralIdentifier;
private ReferralType type;
}

View File

@@ -0,0 +1,16 @@
package dev.sheldan.oneplus.bot.modules.referral.model.template;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
import net.dv8tion.jda.api.entities.Member;
import java.util.List;
@Getter
@Setter
@Builder
public class ReferralPostModel {
private Member postingMember;
private List<Referral> referrals;
}

View File

@@ -0,0 +1,14 @@
package dev.sheldan.oneplus.bot.modules.referral.model.template;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
import java.time.Instant;
@Getter
@Setter
@Builder
public class ReferralTooRecentModel {
private Instant nextReferralDate;
}

View File

@@ -0,0 +1,12 @@
package dev.sheldan.oneplus.bot.modules.referral.repository;
import dev.sheldan.oneplus.bot.modules.referral.model.database.ReferralUserInAServer;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.util.Optional;
@Repository
public interface ReferralUserInAServerRepository extends JpaRepository<ReferralUserInAServer, Long> {
Optional<ReferralUserInAServer> findByServer_IdAndUser_UserReference_Id(Long serverId, Long userId);
}

View File

@@ -0,0 +1,77 @@
package dev.sheldan.oneplus.bot.modules.referral.service;
import dev.sheldan.abstracto.core.models.ServerUser;
import dev.sheldan.oneplus.bot.modules.referral.model.ReferralType;
import dev.sheldan.oneplus.bot.modules.referral.model.database.ReferralUserInAServer;
import dev.sheldan.oneplus.bot.modules.referral.model.template.Referral;
import dev.sheldan.oneplus.bot.modules.referral.service.management.ReferralUserManagementServiceBean;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.Message;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@Component
public class ReferralServiceBean {
@Value("${oneplus.bot.referral.referralRepostDays}")
private Long repostDurationDays;
@Autowired
private ReferralUserManagementServiceBean referralUserManagementServiceBean;
private final Pattern referralPattern = Pattern.compile("(?<whole>https?://(?:www\\.)?oneplus\\.(?:[a-z]{1,63})[^\\s]*invite(?:#(?<identifier>[^\\s]+)|.+=([^\\s&]+)))");
public List<Referral> getReferralsFromMessage(Message message) {
List<Referral> referrals = new ArrayList<>();
Matcher matcher = referralPattern.matcher(message.getContentRaw());
while(matcher.find()) {
String fullUrl = matcher.group("whole");
String referralIdentifier = matcher.group("identifier");
Referral referral = Referral
.builder()
.referralLink(fullUrl)
.type(getType(referralIdentifier, fullUrl))
.referralIdentifier(referralIdentifier)
.build();
referrals.add(referral);
}
return referrals;
}
private ReferralType getType(String identifier, String fullUrl) {
if(identifier.length() < 20) {
return ReferralType.SMARTPHONE;
} else if(fullUrl.contains(".in")) {
return ReferralType.SMARTPHONE_INDIA;
} else {
return ReferralType.ACCESSORIES;
}
}
public void updateDbState(ServerUser serverUser) {
Optional<ReferralUserInAServer> userOptional = referralUserManagementServiceBean.getReferralFromDb(serverUser);
if(userOptional.isPresent()) {
userOptional.get().setLastReferralPost(Instant.now());
} else {
referralUserManagementServiceBean.createReferralUser(serverUser);
}
}
public Instant getNextReferralDate(Member member) {
ServerUser serverUser = ServerUser.fromMember(member);
Optional<ReferralUserInAServer> userOptional = referralUserManagementServiceBean.getReferralFromDb(serverUser);
return userOptional.map(referralUserInAServer -> referralUserInAServer
.getLastReferralPost()
.plus(repostDurationDays, ChronoUnit.DAYS))
.orElse(Instant.now());
}
}

View File

@@ -0,0 +1,38 @@
package dev.sheldan.oneplus.bot.modules.referral.service.management;
import dev.sheldan.abstracto.core.models.ServerUser;
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
import dev.sheldan.oneplus.bot.modules.referral.model.database.ReferralUserInAServer;
import dev.sheldan.oneplus.bot.modules.referral.repository.ReferralUserInAServerRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.time.Instant;
import java.util.Optional;
@Component
public class ReferralUserManagementServiceBean {
@Autowired
private ReferralUserInAServerRepository repository;
@Autowired
private UserInServerManagementService userInServerManagementService;
public Optional<ReferralUserInAServer> getReferralFromDb(ServerUser serverUser) {
return repository.findByServer_IdAndUser_UserReference_Id(serverUser.getServerId(), serverUser.getUserId());
}
public ReferralUserInAServer createReferralUser(ServerUser serverUser) {
AUserInAServer userInAServer = userInServerManagementService.loadOrCreateUser(serverUser);
ReferralUserInAServer user = ReferralUserInAServer
.builder()
.user(userInAServer)
.id(userInAServer.getUserInServerId())
.lastReferralPost(Instant.now())
.server(userInAServer.getServerReference())
.build();
return repository.save(user);
}
}

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="referral-tables/tables.xml" relativeToChangelogFile="true"/>
<include file="referral-seedData/data.xml" relativeToChangelogFile="true"/>
</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="feature.xml" relativeToChangelogFile="true"/>
</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="referral_feature-insertion">
<insert tableName="feature">
<column name="key" value="referral"/>
</insert>
</changeSet>
</databaseChangeLog>

View File

@@ -0,0 +1,35 @@
<?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="referral_user_in_server-table">
<createTable tableName="referral_user_in_server">
<column name="id" type="BIGINT">
<constraints nullable="false" primaryKey="true" primaryKeyName="referral_user_in_server_pkey"/>
</column>
<column name="created" type="TIMESTAMP WITHOUT TIME ZONE">
<constraints nullable="true"/>
</column>
<column name="updated" type="TIMESTAMP WITHOUT TIME ZONE"/>
<column name="last_referral_post" type="TIMESTAMP WITHOUT TIME ZONE" />
<column name="server_id" type="BIGINT">
<constraints nullable="false"/>
</column>
</createTable>
<addForeignKeyConstraint baseColumnNames="server_id" baseTableName="referral_user_in_server" constraintName="fk_referral_user_in_server_server" deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION" referencedColumnNames="id" referencedTableName="server" validate="true"/>
<addForeignKeyConstraint baseColumnNames="id" baseTableName="referral_user_in_server" constraintName="fk_referral_user_in_server_user" deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION" referencedColumnNames="user_in_server_id" referencedTableName="user_in_server" validate="true"/>
<sql>
DROP TRIGGER IF EXISTS referral_user_in_server_update_trigger ON referral_user_in_server;
CREATE TRIGGER referral_user_in_server_update_trigger BEFORE UPDATE ON referral_user_in_server FOR EACH ROW EXECUTE PROCEDURE update_trigger_procedure();
</sql>
<sql>
DROP TRIGGER IF EXISTS referral_user_in_server_insert_trigger ON referral_user_in_server;
CREATE TRIGGER referral_user_in_server_insert_trigger BEFORE INSERT ON referral_user_in_server FOR EACH ROW EXECUTE PROCEDURE insert_trigger_procedure();
</sql>
</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="referral_user_in_server.xml" relativeToChangelogFile="true"/>
</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-referral/collection.xml" relativeToChangelogFile="true"/>
</databaseChangeLog>

View File

@@ -0,0 +1,8 @@
abstracto.postTargets.referral.name=referral
abstracto.featureFlags.referral.featureName=referral
abstracto.featureFlags.referral.enabled=false
oneplus.bot.referral.maxReferralCount=2
oneplus.bot.referral.deleteDelaySeconds=7
oneplus.bot.referral.referralRepostDays=14