mirror of
https://github.com/Sheldan/abstracto.git
synced 2026-04-14 11:48:16 +00:00
[AB-80] added tracking of emotes used by server members and configuration
updated sonar scanner version changed some commands to be silent instead of adding a check reaction
This commit is contained in:
@@ -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>
|
||||
@@ -0,0 +1,21 @@
|
||||
package dev.sheldan.abstracto.statistic.config;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.config.ModuleInfo;
|
||||
import dev.sheldan.abstracto.core.command.config.ModuleInterface;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class StatisticModule implements ModuleInterface {
|
||||
|
||||
public static final String STATISTIC = "statistic";
|
||||
|
||||
@Override
|
||||
public ModuleInfo getInfo() {
|
||||
return ModuleInfo.builder().name(STATISTIC).description("Module containing commands related to statistic.").build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getParentModule() {
|
||||
return "default";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package dev.sheldan.abstracto.statistic.emotes.command;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
|
||||
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
|
||||
import dev.sheldan.abstracto.core.command.config.HelpInfo;
|
||||
import dev.sheldan.abstracto.core.command.config.Parameter;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandContext;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.config.FeatureEnum;
|
||||
import dev.sheldan.abstracto.statistic.config.StatisticFeatures;
|
||||
import dev.sheldan.abstracto.statistic.config.StatisticModule;
|
||||
import dev.sheldan.abstracto.statistic.emotes.model.database.TrackedEmote;
|
||||
import dev.sheldan.abstracto.statistic.emotes.service.TrackedEmoteService;
|
||||
import dev.sheldan.abstracto.statistic.emotes.service.management.TrackedEmoteManagementService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
public class DeleteTrackedEmote extends AbstractConditionableCommand {
|
||||
|
||||
@Autowired
|
||||
private TrackedEmoteManagementService trackedEmoteManagementService;
|
||||
|
||||
@Autowired
|
||||
private TrackedEmoteService trackedEmoteService;
|
||||
|
||||
@Override
|
||||
public CommandResult execute(CommandContext commandContext) {
|
||||
checkParameters(commandContext);
|
||||
List<Object> parameters = commandContext.getParameters().getParameters();
|
||||
TrackedEmote fakeTrackedEmote = (TrackedEmote) parameters.get(0);
|
||||
TrackedEmote trackedEmote = trackedEmoteManagementService.loadByTrackedEmoteServer(fakeTrackedEmote.getTrackedEmoteId());
|
||||
trackedEmoteService.deleteTrackedEmote(trackedEmote);
|
||||
return CommandResult.fromSuccess();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandConfiguration getConfiguration() {
|
||||
List<Parameter> parameters = new ArrayList<>();
|
||||
parameters.add(Parameter.builder().name("trackedEmote").templated(true).type(TrackedEmote.class).build());
|
||||
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();
|
||||
return CommandConfiguration.builder()
|
||||
.name("deleteTrackedEmote")
|
||||
.module(StatisticModule.STATISTIC)
|
||||
.templated(true)
|
||||
.supportsEmbedException(true)
|
||||
.causesReaction(true)
|
||||
.parameters(parameters)
|
||||
.help(helpInfo)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeatureEnum getFeature() {
|
||||
return StatisticFeatures.EMOTE_TRACKING;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
package dev.sheldan.abstracto.statistic.emotes.command;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
|
||||
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
|
||||
import dev.sheldan.abstracto.core.command.config.HelpInfo;
|
||||
import dev.sheldan.abstracto.core.command.config.Parameter;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandContext;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.config.FeatureEnum;
|
||||
import dev.sheldan.abstracto.core.service.ChannelService;
|
||||
import dev.sheldan.abstracto.core.utils.FutureUtils;
|
||||
import dev.sheldan.abstracto.statistic.config.StatisticFeatures;
|
||||
import dev.sheldan.abstracto.statistic.config.StatisticModule;
|
||||
import dev.sheldan.abstracto.statistic.emotes.model.EmoteStatsModel;
|
||||
import dev.sheldan.abstracto.statistic.emotes.service.UsedEmoteService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class DeletedEmoteStats extends AbstractConditionableCommand {
|
||||
|
||||
@Autowired
|
||||
private UsedEmoteService usedEmoteService;
|
||||
|
||||
@Autowired
|
||||
private ChannelService channelService;
|
||||
|
||||
public static final String EMOTE_STATS_STATIC_DELETED_RESPONSE = "deletedEmoteStats_static_response";
|
||||
public static final String EMOTE_STATS_ANIMATED_DELETED_RESPONSE = "deletedEmoteStats_animated_response";
|
||||
|
||||
@Override
|
||||
public CompletableFuture<CommandResult> executeAsync(CommandContext commandContext) {
|
||||
checkParameters(commandContext);
|
||||
List<Object> parameters = commandContext.getParameters().getParameters();
|
||||
Instant statsSince = Instant.EPOCH;
|
||||
if(!parameters.isEmpty()) {
|
||||
Duration duration = (Duration) parameters.get(0);
|
||||
statsSince = Instant.now().minus(duration);
|
||||
}
|
||||
EmoteStatsModel emoteStatsModel = usedEmoteService.getDeletedEmoteStatsForServerSince(commandContext.getUserInitiatedContext().getServer(), statsSince);
|
||||
List<CompletableFuture<Message>> messagePromises = new ArrayList<>();
|
||||
if(!emoteStatsModel.getStaticEmotes().isEmpty()) {
|
||||
log.trace("Deleted emote stats has {} static emotes since {}.", emoteStatsModel.getStaticEmotes().size(), statsSince);
|
||||
messagePromises.addAll(channelService.sendEmbedTemplateInChannel(EMOTE_STATS_STATIC_DELETED_RESPONSE, emoteStatsModel, commandContext.getChannel()));
|
||||
}
|
||||
if(!emoteStatsModel.getAnimatedEmotes().isEmpty()) {
|
||||
log.trace("Deleted emote stats has {} animated emotes since {}.", emoteStatsModel.getAnimatedEmotes(), statsSince);
|
||||
messagePromises.addAll(channelService.sendEmbedTemplateInChannel(EMOTE_STATS_ANIMATED_DELETED_RESPONSE, emoteStatsModel, commandContext.getChannel()));
|
||||
}
|
||||
if(!emoteStatsModel.areStatsAvailable()) {
|
||||
log.info("No delete emote stats available for guild {} since {}.", commandContext.getGuild().getIdLong(), statsSince);
|
||||
messagePromises.addAll(channelService.sendEmbedTemplateInChannel(EmoteStats.EMOTE_STATS_NO_STATS_AVAILABLE, new Object(), commandContext.getChannel()));
|
||||
}
|
||||
|
||||
return FutureUtils.toSingleFutureGeneric(messagePromises)
|
||||
.thenApply(unused -> CommandResult.fromIgnored());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandConfiguration getConfiguration() {
|
||||
List<Parameter> parameters = new ArrayList<>();
|
||||
parameters.add(Parameter.builder().name("period").templated(true).optional(true).type(Duration.class).build());
|
||||
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();
|
||||
return CommandConfiguration.builder()
|
||||
.name("deletedEmoteStats")
|
||||
.module(StatisticModule.STATISTIC)
|
||||
.templated(true)
|
||||
.async(true)
|
||||
.supportsEmbedException(true)
|
||||
.causesReaction(true)
|
||||
.parameters(parameters)
|
||||
.help(helpInfo)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeatureEnum getFeature() {
|
||||
return StatisticFeatures.EMOTE_TRACKING;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
package dev.sheldan.abstracto.statistic.emotes.command;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
|
||||
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
|
||||
import dev.sheldan.abstracto.core.command.config.HelpInfo;
|
||||
import dev.sheldan.abstracto.core.command.config.Parameter;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandContext;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.config.FeatureEnum;
|
||||
import dev.sheldan.abstracto.statistic.config.StatisticFeatures;
|
||||
import dev.sheldan.abstracto.statistic.config.StatisticModule;
|
||||
import dev.sheldan.abstracto.statistic.emotes.model.database.TrackedEmote;
|
||||
import dev.sheldan.abstracto.statistic.emotes.service.TrackedEmoteService;
|
||||
import dev.sheldan.abstracto.statistic.emotes.service.management.TrackedEmoteManagementService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
public class DisableEmoteTracking extends AbstractConditionableCommand {
|
||||
|
||||
@Autowired
|
||||
private TrackedEmoteService trackedEmoteService;
|
||||
|
||||
@Autowired
|
||||
private TrackedEmoteManagementService trackedEmoteManagementService;
|
||||
|
||||
@Override
|
||||
public CommandResult execute(CommandContext commandContext) {
|
||||
checkParameters(commandContext);
|
||||
List<Object> parameters = commandContext.getParameters().getParameters();
|
||||
if(!parameters.isEmpty()) {
|
||||
TrackedEmote fakeTrackedEmote = (TrackedEmote) parameters.get(0);
|
||||
TrackedEmote trackedEmote = trackedEmoteManagementService.loadByTrackedEmoteServer(fakeTrackedEmote.getTrackedEmoteId());
|
||||
trackedEmoteManagementService.disableTrackedEmote(trackedEmote);
|
||||
} else {
|
||||
trackedEmoteService.disableEmoteTracking(commandContext.getGuild());
|
||||
}
|
||||
return CommandResult.fromSuccess();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandConfiguration getConfiguration() {
|
||||
List<Parameter> parameters = new ArrayList<>();
|
||||
parameters.add(Parameter.builder().name("trackedEmote").templated(true).optional(true).type(TrackedEmote.class).build());
|
||||
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();
|
||||
return CommandConfiguration.builder()
|
||||
.name("disableEmoteTracking")
|
||||
.module(StatisticModule.STATISTIC)
|
||||
.templated(true)
|
||||
.supportsEmbedException(true)
|
||||
.causesReaction(true)
|
||||
.parameters(parameters)
|
||||
.help(helpInfo)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeatureEnum getFeature() {
|
||||
return StatisticFeatures.EMOTE_TRACKING;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
package dev.sheldan.abstracto.statistic.emotes.command;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
|
||||
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
|
||||
import dev.sheldan.abstracto.core.command.config.HelpInfo;
|
||||
import dev.sheldan.abstracto.core.command.config.Parameter;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandContext;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.config.FeatureEnum;
|
||||
import dev.sheldan.abstracto.core.service.ChannelService;
|
||||
import dev.sheldan.abstracto.core.service.FeatureModeService;
|
||||
import dev.sheldan.abstracto.core.utils.FutureUtils;
|
||||
import dev.sheldan.abstracto.statistic.config.StatisticFeatures;
|
||||
import dev.sheldan.abstracto.statistic.config.StatisticModule;
|
||||
import dev.sheldan.abstracto.statistic.emotes.model.EmoteStatsModel;
|
||||
import dev.sheldan.abstracto.statistic.emotes.service.UsedEmoteService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class EmoteStats extends AbstractConditionableCommand {
|
||||
|
||||
@Autowired
|
||||
private UsedEmoteService usedEmoteService;
|
||||
|
||||
@Autowired
|
||||
private ChannelService channelService;
|
||||
|
||||
@Autowired
|
||||
private FeatureModeService featureModeService;
|
||||
|
||||
public static final String EMOTE_STATS_STATIC_RESPONSE = "emoteStats_static_response";
|
||||
public static final String EMOTE_STATS_ANIMATED_RESPONSE = "emoteStats_animated_response";
|
||||
public static final String EMOTE_STATS_NO_STATS_AVAILABLE = "emoteStats_no_stats_available";
|
||||
|
||||
@Override
|
||||
public CompletableFuture<CommandResult> executeAsync(CommandContext commandContext) {
|
||||
checkParameters(commandContext);
|
||||
List<Object> parameters = commandContext.getParameters().getParameters();
|
||||
Instant statsSince = Instant.EPOCH;
|
||||
if(!parameters.isEmpty()) {
|
||||
Duration duration = (Duration) parameters.get(0);
|
||||
statsSince = Instant.now().minus(duration);
|
||||
}
|
||||
EmoteStatsModel emoteStatsModel = usedEmoteService.getActiveEmoteStatsForServerSince(commandContext.getUserInitiatedContext().getServer(), statsSince);
|
||||
List<CompletableFuture<Message>> messagePromises = new ArrayList<>();
|
||||
if(!emoteStatsModel.getStaticEmotes().isEmpty()) {
|
||||
log.trace("Emote stats has {} static emotes since {}.", emoteStatsModel.getStaticEmotes().size(), statsSince);
|
||||
messagePromises.addAll(channelService.sendEmbedTemplateInChannel(EMOTE_STATS_STATIC_RESPONSE, emoteStatsModel, commandContext.getChannel()));
|
||||
}
|
||||
if(!emoteStatsModel.getAnimatedEmotes().isEmpty()) {
|
||||
log.trace("Emote stats has {} animated emotes since {}.", emoteStatsModel.getAnimatedEmotes(), statsSince);
|
||||
messagePromises.addAll(channelService.sendEmbedTemplateInChannel(EMOTE_STATS_ANIMATED_RESPONSE, emoteStatsModel, commandContext.getChannel()));
|
||||
}
|
||||
if(!emoteStatsModel.areStatsAvailable()) {
|
||||
log.info("No emote stats available for guild {} since {}.", commandContext.getGuild().getIdLong(), statsSince);
|
||||
messagePromises.addAll(channelService.sendEmbedTemplateInChannel(EMOTE_STATS_NO_STATS_AVAILABLE, new Object(), commandContext.getChannel()));
|
||||
}
|
||||
|
||||
return FutureUtils.toSingleFutureGeneric(messagePromises)
|
||||
.thenApply(unused -> CommandResult.fromIgnored());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandConfiguration getConfiguration() {
|
||||
List<Parameter> parameters = new ArrayList<>();
|
||||
parameters.add(Parameter.builder().name("period").templated(true).optional(true).type(Duration.class).build());
|
||||
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();
|
||||
return CommandConfiguration.builder()
|
||||
.name("emoteStats")
|
||||
.module(StatisticModule.STATISTIC)
|
||||
.templated(true)
|
||||
.async(true)
|
||||
.supportsEmbedException(true)
|
||||
.causesReaction(true)
|
||||
.parameters(parameters)
|
||||
.help(helpInfo)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeatureEnum getFeature() {
|
||||
return StatisticFeatures.EMOTE_TRACKING;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
package dev.sheldan.abstracto.statistic.emotes.command;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
|
||||
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
|
||||
import dev.sheldan.abstracto.core.command.config.HelpInfo;
|
||||
import dev.sheldan.abstracto.core.command.config.Parameter;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandContext;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.config.FeatureEnum;
|
||||
import dev.sheldan.abstracto.core.exception.AbstractoRunTimeException;
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import dev.sheldan.abstracto.core.service.ChannelService;
|
||||
import dev.sheldan.abstracto.core.service.management.ServerManagementService;
|
||||
import dev.sheldan.abstracto.core.utils.FileUtils;
|
||||
import dev.sheldan.abstracto.core.utils.FutureUtils;
|
||||
import dev.sheldan.abstracto.statistic.config.StatisticFeatures;
|
||||
import dev.sheldan.abstracto.statistic.config.StatisticModule;
|
||||
import dev.sheldan.abstracto.statistic.emotes.exception.DownloadEmoteStatsFileTooBigException;
|
||||
import dev.sheldan.abstracto.statistic.emotes.model.DownloadEmoteStatsModel;
|
||||
import dev.sheldan.abstracto.statistic.emotes.model.database.UsedEmote;
|
||||
import dev.sheldan.abstracto.statistic.emotes.service.management.UsedEmoteManagementService;
|
||||
import dev.sheldan.abstracto.templating.model.MessageToSend;
|
||||
import dev.sheldan.abstracto.templating.service.TemplateService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class ExportEmoteStats extends AbstractConditionableCommand {
|
||||
|
||||
public static final String DOWNLOAD_EMOTE_STATS_NO_STATS_AVAILABLE_RESPONSE_TEMPLATE_KEY = "downloadEmoteStats_no_stats_available_response";
|
||||
public static final String DOWNLOAD_EMOTE_STATS_FILE_NAME_TEMPLATE_KEY = "downloadEmoteStats_file_name";
|
||||
public static final String DOWNLOAD_EMOTE_STATS_FILE_CONTENT_TEMPLATE_KEY = "downloadEmoteStats_file_content";
|
||||
public static final String DOWNLOAD_EMOTE_STATS_RESPONSE_TEMPLATE_KEY = "downloadEmoteStats_response";
|
||||
@Autowired
|
||||
private ServerManagementService serverManagementService;
|
||||
|
||||
@Autowired
|
||||
private TemplateService templateService;
|
||||
|
||||
@Autowired
|
||||
private ChannelService channelService;
|
||||
|
||||
@Autowired
|
||||
private UsedEmoteManagementService usedEmoteManagementService;
|
||||
|
||||
@Autowired
|
||||
private FileUtils fileUtils;
|
||||
|
||||
@Override
|
||||
public CompletableFuture<CommandResult> executeAsync(CommandContext commandContext) {
|
||||
checkParameters(commandContext);
|
||||
List<Object> parameters = commandContext.getParameters().getParameters();
|
||||
Instant statsSince = Instant.EPOCH;
|
||||
if(!parameters.isEmpty()) {
|
||||
Duration duration = (Duration) parameters.get(0);
|
||||
statsSince = Instant.now().minus(duration);
|
||||
}
|
||||
AServer actualServer = serverManagementService.loadServer(commandContext.getGuild().getIdLong());
|
||||
List<UsedEmote> usedEmotes = usedEmoteManagementService.loadEmoteUsagesForServerSince(actualServer, statsSince);
|
||||
if(usedEmotes.isEmpty()) {
|
||||
return FutureUtils.toSingleFutureGeneric(channelService.sendEmbedTemplateInChannel(DOWNLOAD_EMOTE_STATS_NO_STATS_AVAILABLE_RESPONSE_TEMPLATE_KEY, new Object(), commandContext.getChannel()))
|
||||
.thenApply(unused -> CommandResult.fromIgnored());
|
||||
}
|
||||
// info might not be nice to handle in the template, and 1970 would look weird to users
|
||||
// effectively this means if its null its EPOCH, so it would be possible to render it still
|
||||
Instant toUseForModel = statsSince != Instant.EPOCH ? statsSince : null;
|
||||
DownloadEmoteStatsModel model = DownloadEmoteStatsModel
|
||||
.builder()
|
||||
.emotes(usedEmotes)
|
||||
.guild(commandContext.getGuild())
|
||||
.downloadDate(Instant.now())
|
||||
.requester(commandContext.getAuthor())
|
||||
.statsSince(toUseForModel)
|
||||
.build();
|
||||
String fileName = templateService.renderTemplate(DOWNLOAD_EMOTE_STATS_FILE_NAME_TEMPLATE_KEY, model);
|
||||
String fileContent = templateService.renderTemplate(DOWNLOAD_EMOTE_STATS_FILE_CONTENT_TEMPLATE_KEY, model);
|
||||
File tempFile = fileUtils.createTempFile(fileName);
|
||||
try {
|
||||
fileUtils.writeContentToFile(tempFile, fileContent);
|
||||
long maxFileSize = commandContext.getGuild().getMaxFileSize();
|
||||
if(maxFileSize < tempFile.length()) {
|
||||
throw new DownloadEmoteStatsFileTooBigException(tempFile.length(), maxFileSize);
|
||||
}
|
||||
MessageToSend messageToSend = templateService.renderEmbedTemplate(DOWNLOAD_EMOTE_STATS_RESPONSE_TEMPLATE_KEY, model);
|
||||
messageToSend.setFileToSend(tempFile);
|
||||
return FutureUtils.toSingleFutureGeneric(channelService.sendMessageToSendToChannel(messageToSend, commandContext.getChannel()))
|
||||
.thenApply(unused -> CommandResult.fromIgnored());
|
||||
} catch (IOException e) {
|
||||
throw new AbstractoRunTimeException(e);
|
||||
} finally {
|
||||
try {
|
||||
fileUtils.safeDelete(tempFile);
|
||||
} catch (IOException e) {
|
||||
log.error("Failed to delete temporary export emote statistics file {}.", tempFile.getAbsoluteFile(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandConfiguration getConfiguration() {
|
||||
List<Parameter> parameters = new ArrayList<>();
|
||||
parameters.add(Parameter.builder().name("period").templated(true).optional(true).type(Duration.class).build());
|
||||
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();
|
||||
return CommandConfiguration.builder()
|
||||
.name("exportEmoteStats")
|
||||
.module(StatisticModule.STATISTIC)
|
||||
.templated(true)
|
||||
.async(true)
|
||||
.supportsEmbedException(true)
|
||||
.causesReaction(true)
|
||||
.parameters(parameters)
|
||||
.help(helpInfo)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeatureEnum getFeature() {
|
||||
return StatisticFeatures.EMOTE_TRACKING;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
package dev.sheldan.abstracto.statistic.emotes.command;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
|
||||
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
|
||||
import dev.sheldan.abstracto.core.command.config.HelpInfo;
|
||||
import dev.sheldan.abstracto.core.command.config.Parameter;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandContext;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.config.FeatureEnum;
|
||||
import dev.sheldan.abstracto.core.config.FeatureMode;
|
||||
import dev.sheldan.abstracto.core.service.ChannelService;
|
||||
import dev.sheldan.abstracto.core.service.FeatureModeService;
|
||||
import dev.sheldan.abstracto.core.utils.FutureUtils;
|
||||
import dev.sheldan.abstracto.statistic.config.StatisticFeatures;
|
||||
import dev.sheldan.abstracto.statistic.config.StatisticModule;
|
||||
import dev.sheldan.abstracto.statistic.emotes.config.EmoteTrackingMode;
|
||||
import dev.sheldan.abstracto.statistic.emotes.model.EmoteStatsModel;
|
||||
import dev.sheldan.abstracto.statistic.emotes.service.UsedEmoteService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class ExternalEmoteStats extends AbstractConditionableCommand {
|
||||
|
||||
@Autowired
|
||||
private UsedEmoteService usedEmoteService;
|
||||
|
||||
@Autowired
|
||||
private ChannelService channelService;
|
||||
|
||||
@Autowired
|
||||
private FeatureModeService featureModeService;
|
||||
|
||||
public static final String EMOTE_STATS_STATIC_EXTERNAL_RESPONSE = "externalEmoteStats_static_response";
|
||||
public static final String EMOTE_STATS_ANIMATED_EXTERNAL_RESPONSE = "externalEmoteStats_animated_response";
|
||||
|
||||
@Override
|
||||
public CompletableFuture<CommandResult> executeAsync(CommandContext commandContext) {
|
||||
checkParameters(commandContext);
|
||||
List<Object> parameters = commandContext.getParameters().getParameters();
|
||||
Instant statsSince = Instant.EPOCH;
|
||||
if(!parameters.isEmpty()) {
|
||||
Duration duration = (Duration) parameters.get(0);
|
||||
statsSince = Instant.now().minus(duration);
|
||||
}
|
||||
EmoteStatsModel emoteStatsModel = usedEmoteService.getExternalEmoteStatsForServerSince(commandContext.getUserInitiatedContext().getServer(), statsSince);
|
||||
List<CompletableFuture<Message>> messagePromises = new ArrayList<>();
|
||||
|
||||
if(!emoteStatsModel.getStaticEmotes().isEmpty()) {
|
||||
log.trace("External emote stats has {} static emotes since {}.", emoteStatsModel.getStaticEmotes().size(), statsSince);
|
||||
messagePromises.addAll(channelService.sendEmbedTemplateInChannel(EMOTE_STATS_STATIC_EXTERNAL_RESPONSE, emoteStatsModel, commandContext.getChannel()));
|
||||
}
|
||||
if(!emoteStatsModel.getAnimatedEmotes().isEmpty()) {
|
||||
log.trace("External emote stats has {} animated emotes since {}.", emoteStatsModel.getAnimatedEmotes(), statsSince);
|
||||
messagePromises.addAll(channelService.sendEmbedTemplateInChannel(EMOTE_STATS_ANIMATED_EXTERNAL_RESPONSE, emoteStatsModel, commandContext.getChannel()));
|
||||
}
|
||||
if(!emoteStatsModel.areStatsAvailable()) {
|
||||
log.info("No external emote stats available for guild {} since {}.", commandContext.getGuild().getIdLong(), statsSince);
|
||||
messagePromises.addAll(channelService.sendEmbedTemplateInChannel(EmoteStats.EMOTE_STATS_NO_STATS_AVAILABLE, new Object(), commandContext.getChannel()));
|
||||
}
|
||||
|
||||
return FutureUtils.toSingleFutureGeneric(messagePromises)
|
||||
.thenApply(unused -> CommandResult.fromIgnored());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandConfiguration getConfiguration() {
|
||||
List<Parameter> parameters = new ArrayList<>();
|
||||
parameters.add(Parameter.builder().name("period").templated(true).optional(true).type(Duration.class).build());
|
||||
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();
|
||||
return CommandConfiguration.builder()
|
||||
.name("externalEmoteStats")
|
||||
.module(StatisticModule.STATISTIC)
|
||||
.templated(true)
|
||||
.async(true)
|
||||
.supportsEmbedException(true)
|
||||
.causesReaction(true)
|
||||
.parameters(parameters)
|
||||
.help(helpInfo)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeatureEnum getFeature() {
|
||||
return StatisticFeatures.EMOTE_TRACKING;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<FeatureMode> getFeatureModeLimitations() {
|
||||
return Arrays.asList(EmoteTrackingMode.EXTERNAL_EMOTES);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
package dev.sheldan.abstracto.statistic.emotes.command;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
|
||||
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
|
||||
import dev.sheldan.abstracto.core.command.config.HelpInfo;
|
||||
import dev.sheldan.abstracto.core.command.config.Parameter;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandContext;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.config.FeatureEnum;
|
||||
import dev.sheldan.abstracto.statistic.config.StatisticFeatures;
|
||||
import dev.sheldan.abstracto.statistic.config.StatisticModule;
|
||||
import dev.sheldan.abstracto.statistic.emotes.model.database.TrackedEmote;
|
||||
import dev.sheldan.abstracto.statistic.emotes.service.UsedEmoteService;
|
||||
import dev.sheldan.abstracto.statistic.emotes.service.management.TrackedEmoteManagementService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
public class PurgeEmoteStats extends AbstractConditionableCommand {
|
||||
|
||||
@Autowired
|
||||
private TrackedEmoteManagementService trackedEmoteManagementService;
|
||||
|
||||
@Autowired
|
||||
private UsedEmoteService usedEmoteService;
|
||||
|
||||
@Override
|
||||
public CommandResult execute(CommandContext commandContext) {
|
||||
checkParameters(commandContext);
|
||||
List<Object> parameters = commandContext.getParameters().getParameters();
|
||||
TrackedEmote fakeTrackedEmote = (TrackedEmote) parameters.get(0);
|
||||
TrackedEmote trackedEmote = trackedEmoteManagementService.loadByTrackedEmoteServer(fakeTrackedEmote.getTrackedEmoteId());
|
||||
Instant since = Instant.EPOCH;
|
||||
if(parameters.size() > 1) {
|
||||
Duration parameter = (Duration) parameters.get(1);
|
||||
since = Instant.now().minus(parameter);
|
||||
}
|
||||
usedEmoteService.purgeEmoteUsagesSince(trackedEmote, since);
|
||||
return CommandResult.fromSuccess();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandConfiguration getConfiguration() {
|
||||
List<Parameter> parameters = new ArrayList<>();
|
||||
parameters.add(Parameter.builder().name("trackedEmote").templated(true).type(TrackedEmote.class).build());
|
||||
parameters.add(Parameter.builder().name("period").templated(true).optional(true).type(Duration.class).build());
|
||||
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();
|
||||
return CommandConfiguration.builder()
|
||||
.name("purgeEmoteStats")
|
||||
.module(StatisticModule.STATISTIC)
|
||||
.templated(true)
|
||||
.supportsEmbedException(true)
|
||||
.causesReaction(true)
|
||||
.parameters(parameters)
|
||||
.help(helpInfo)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeatureEnum getFeature() {
|
||||
return StatisticFeatures.EMOTE_TRACKING;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package dev.sheldan.abstracto.statistic.emotes.command;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
|
||||
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
|
||||
import dev.sheldan.abstracto.core.command.config.HelpInfo;
|
||||
import dev.sheldan.abstracto.core.command.config.Parameter;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandContext;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.config.FeatureEnum;
|
||||
import dev.sheldan.abstracto.statistic.config.StatisticFeatures;
|
||||
import dev.sheldan.abstracto.statistic.config.StatisticModule;
|
||||
import dev.sheldan.abstracto.statistic.emotes.service.TrackedEmoteService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
public class ResetEmoteStats extends AbstractConditionableCommand {
|
||||
|
||||
@Autowired
|
||||
private TrackedEmoteService trackedEmoteService;
|
||||
|
||||
@Override
|
||||
public CommandResult execute(CommandContext commandContext) {
|
||||
trackedEmoteService.resetEmoteStats(commandContext.getGuild());
|
||||
return CommandResult.fromSuccess();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandConfiguration getConfiguration() {
|
||||
List<Parameter> parameters = new ArrayList<>();
|
||||
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();
|
||||
return CommandConfiguration.builder()
|
||||
.name("resetEmoteStats")
|
||||
.module(StatisticModule.STATISTIC)
|
||||
.templated(true)
|
||||
.supportsEmbedException(true)
|
||||
.causesReaction(true)
|
||||
.parameters(parameters)
|
||||
.help(helpInfo)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeatureEnum getFeature() {
|
||||
return StatisticFeatures.EMOTE_TRACKING;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
package dev.sheldan.abstracto.statistic.emotes.command;
|
||||
|
||||
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.exception.AbstractoTemplatedException;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandContext;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.config.FeatureEnum;
|
||||
import dev.sheldan.abstracto.core.config.FeatureMode;
|
||||
import dev.sheldan.abstracto.core.service.ChannelService;
|
||||
import dev.sheldan.abstracto.core.utils.FutureUtils;
|
||||
import dev.sheldan.abstracto.statistic.config.StatisticFeatures;
|
||||
import dev.sheldan.abstracto.statistic.config.StatisticModule;
|
||||
import dev.sheldan.abstracto.statistic.emotes.config.EmoteTrackingMode;
|
||||
import dev.sheldan.abstracto.statistic.emotes.model.database.TrackedEmote;
|
||||
import dev.sheldan.abstracto.statistic.emotes.service.management.TrackedEmoteManagementService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
@Component
|
||||
public class ShowExternalTrackedEmote extends AbstractConditionableCommand {
|
||||
|
||||
public static final String SHOW_EXTERNAL_TRACKED_EMOTE_RESPONSE_TEMPLATE_KEY = "showExternalTrackedEmote_response";
|
||||
@Autowired
|
||||
private ChannelService channelService;
|
||||
|
||||
@Autowired
|
||||
private TrackedEmoteManagementService trackedEmoteManagementService;
|
||||
|
||||
@Override
|
||||
public CompletableFuture<CommandResult> executeAsync(CommandContext commandContext) {
|
||||
checkParameters(commandContext);
|
||||
List<Object> parameters = commandContext.getParameters().getParameters();
|
||||
TrackedEmote fakeTrackedEmote = (TrackedEmote) parameters.get(0);
|
||||
TrackedEmote trackedEmote = trackedEmoteManagementService.loadByTrackedEmoteServer(fakeTrackedEmote.getTrackedEmoteId());
|
||||
if(!trackedEmote.getExternal()) {
|
||||
throw new AbstractoTemplatedException("Emote is not external", "showExternalTrackedEmote_emote_is_not_external");
|
||||
}
|
||||
return FutureUtils.toSingleFutureGeneric(channelService.sendEmbedTemplateInChannel(SHOW_EXTERNAL_TRACKED_EMOTE_RESPONSE_TEMPLATE_KEY, trackedEmote, commandContext.getChannel()))
|
||||
.thenApply(unused -> CommandResult.fromIgnored());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandConfiguration getConfiguration() {
|
||||
List<Parameter> parameters = new ArrayList<>();
|
||||
parameters.add(Parameter.builder().name("trackedEmote").templated(true).type(TrackedEmote.class).build());
|
||||
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();
|
||||
return CommandConfiguration.builder()
|
||||
.name("showExternalTrackedEmote")
|
||||
.module(StatisticModule.STATISTIC)
|
||||
.templated(true)
|
||||
.async(true)
|
||||
.supportsEmbedException(true)
|
||||
.causesReaction(true)
|
||||
.parameters(parameters)
|
||||
.help(helpInfo)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeatureEnum getFeature() {
|
||||
return StatisticFeatures.EMOTE_TRACKING;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<FeatureMode> getFeatureModeLimitations() {
|
||||
return Arrays.asList(EmoteTrackingMode.EXTERNAL_EMOTES);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
package dev.sheldan.abstracto.statistic.emotes.command;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
|
||||
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
|
||||
import dev.sheldan.abstracto.core.command.config.HelpInfo;
|
||||
import dev.sheldan.abstracto.core.command.config.Parameter;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandContext;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.config.FeatureEnum;
|
||||
import dev.sheldan.abstracto.core.service.ChannelService;
|
||||
import dev.sheldan.abstracto.core.service.FeatureModeService;
|
||||
import dev.sheldan.abstracto.core.utils.FutureUtils;
|
||||
import dev.sheldan.abstracto.statistic.config.StatisticFeatures;
|
||||
import dev.sheldan.abstracto.statistic.config.StatisticModule;
|
||||
import dev.sheldan.abstracto.statistic.emotes.config.EmoteTrackingMode;
|
||||
import dev.sheldan.abstracto.statistic.emotes.model.TrackedEmoteOverview;
|
||||
import dev.sheldan.abstracto.statistic.emotes.service.TrackedEmoteService;
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
@Component
|
||||
public class ShowTrackedEmotes extends AbstractConditionableCommand {
|
||||
|
||||
@Autowired
|
||||
private TrackedEmoteService trackedEmoteService;
|
||||
|
||||
@Autowired
|
||||
private ChannelService channelService;
|
||||
|
||||
@Autowired
|
||||
private FeatureModeService featureModeService;
|
||||
|
||||
public static final String EMOTE_STATS_STATIC_RESPONSE = "showTrackedEmotes_static_response";
|
||||
public static final String EMOTE_STATS_ANIMATED_RESPONSE = "showTrackedEmotes_animated_response";
|
||||
public static final String EMOTE_STATS_EXTERNAL_ANIMATED_RESPONSE = "showTrackedEmotes_external_animated_response";
|
||||
public static final String EMOTE_STATS_EXTERNAL_STATIC_RESPONSE = "showTrackedEmotes_external_static_response";
|
||||
public static final String EMOTE_STATS_DELETED_STATIC_RESPONSE = "showTrackedEmotes_deleted_static_response";
|
||||
public static final String EMOTE_STATS_DELETED_ANIMATED_RESPONSE = "showTrackedEmotes_deleted_animated_response";
|
||||
public static final String EMOTE_STATS_NO_STATS_AVAILABLE = "showTrackedEmotes_no_emotes_available";
|
||||
|
||||
@Override
|
||||
public CompletableFuture<CommandResult> executeAsync(CommandContext commandContext) {
|
||||
checkParameters(commandContext);
|
||||
|
||||
Boolean showTrackingDisabled = false;
|
||||
if(!commandContext.getParameters().getParameters().isEmpty()) {
|
||||
showTrackingDisabled = (Boolean) commandContext.getParameters().getParameters().get(0);
|
||||
}
|
||||
|
||||
boolean externalTrackingEnabled = featureModeService.featureModeActive(StatisticFeatures.EMOTE_TRACKING, commandContext.getGuild().getIdLong(), EmoteTrackingMode.EXTERNAL_EMOTES);
|
||||
|
||||
TrackedEmoteOverview trackedEmoteOverview = trackedEmoteService.loadTrackedEmoteOverview(commandContext.getGuild(), showTrackingDisabled);
|
||||
boolean noStatsAvailable = true;
|
||||
List<CompletableFuture<Message>> messagePromises = new ArrayList<>();
|
||||
if(!trackedEmoteOverview.getStaticEmotes().isEmpty()) {
|
||||
noStatsAvailable = false;
|
||||
messagePromises.addAll(channelService.sendEmbedTemplateInChannel(EMOTE_STATS_STATIC_RESPONSE, trackedEmoteOverview, commandContext.getChannel()));
|
||||
}
|
||||
if(!trackedEmoteOverview.getAnimatedEmotes().isEmpty()) {
|
||||
noStatsAvailable = false;
|
||||
messagePromises.addAll(channelService.sendEmbedTemplateInChannel(EMOTE_STATS_ANIMATED_RESPONSE, trackedEmoteOverview, commandContext.getChannel()));
|
||||
}
|
||||
if(!trackedEmoteOverview.getDeletedStaticEmotes().isEmpty()) {
|
||||
noStatsAvailable = false;
|
||||
messagePromises.addAll(channelService.sendEmbedTemplateInChannel(EMOTE_STATS_DELETED_STATIC_RESPONSE, trackedEmoteOverview, commandContext.getChannel()));
|
||||
}
|
||||
if(!trackedEmoteOverview.getDeletedAnimatedEmotes().isEmpty()) {
|
||||
noStatsAvailable = false;
|
||||
messagePromises.addAll(channelService.sendEmbedTemplateInChannel(EMOTE_STATS_DELETED_ANIMATED_RESPONSE, trackedEmoteOverview, commandContext.getChannel()));
|
||||
}
|
||||
if(externalTrackingEnabled) {
|
||||
if(!trackedEmoteOverview.getExternalStaticEmotes().isEmpty()) {
|
||||
noStatsAvailable = false;
|
||||
messagePromises.addAll(channelService.sendEmbedTemplateInChannel(EMOTE_STATS_EXTERNAL_STATIC_RESPONSE, trackedEmoteOverview, commandContext.getChannel()));
|
||||
}
|
||||
if(!trackedEmoteOverview.getExternalAnimatedEmotes().isEmpty()) {
|
||||
noStatsAvailable = false;
|
||||
messagePromises.addAll(channelService.sendEmbedTemplateInChannel(EMOTE_STATS_EXTERNAL_ANIMATED_RESPONSE, trackedEmoteOverview, commandContext.getChannel()));
|
||||
}
|
||||
}
|
||||
if(noStatsAvailable) {
|
||||
messagePromises.addAll(channelService.sendEmbedTemplateInChannel(EMOTE_STATS_NO_STATS_AVAILABLE, new Object(), commandContext.getChannel()));
|
||||
}
|
||||
return FutureUtils.toSingleFutureGeneric(messagePromises)
|
||||
.thenApply(unused -> CommandResult.fromIgnored());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandConfiguration getConfiguration() {
|
||||
List<Parameter> parameters = new ArrayList<>();
|
||||
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();
|
||||
parameters.add(Parameter.builder().name("showAll").templated(true).optional(true).type(Boolean.class).build());
|
||||
return CommandConfiguration.builder()
|
||||
.name("showTrackedEmotes")
|
||||
.module(StatisticModule.STATISTIC)
|
||||
.templated(true)
|
||||
.async(true)
|
||||
.supportsEmbedException(true)
|
||||
.causesReaction(true)
|
||||
.parameters(parameters)
|
||||
.help(helpInfo)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeatureEnum getFeature() {
|
||||
return StatisticFeatures.EMOTE_TRACKING;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package dev.sheldan.abstracto.statistic.emotes.command;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
|
||||
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
|
||||
import dev.sheldan.abstracto.core.command.config.HelpInfo;
|
||||
import dev.sheldan.abstracto.core.command.config.Parameter;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandContext;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.config.FeatureEnum;
|
||||
import dev.sheldan.abstracto.core.service.ChannelService;
|
||||
import dev.sheldan.abstracto.core.utils.FutureUtils;
|
||||
import dev.sheldan.abstracto.statistic.config.StatisticFeatures;
|
||||
import dev.sheldan.abstracto.statistic.config.StatisticModule;
|
||||
import dev.sheldan.abstracto.statistic.emotes.model.TrackedEmoteSynchronizationResult;
|
||||
import dev.sheldan.abstracto.statistic.emotes.service.TrackedEmoteService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
@Component
|
||||
public class SyncTrackedEmotes extends AbstractConditionableCommand {
|
||||
|
||||
public static final String SYNC_TRACKED_EMOTES_RESULT_RESPONSE = "syncTrackedEmotes_result_response";
|
||||
@Autowired
|
||||
private TrackedEmoteService trackedEmoteService;
|
||||
|
||||
@Autowired
|
||||
private ChannelService channelService;
|
||||
|
||||
@Override
|
||||
public CompletableFuture<CommandResult> executeAsync(CommandContext commandContext) {
|
||||
TrackedEmoteSynchronizationResult syncResult = trackedEmoteService.synchronizeTrackedEmotes(commandContext.getGuild());
|
||||
return FutureUtils.toSingleFutureGeneric(channelService.sendEmbedTemplateInChannel(SYNC_TRACKED_EMOTES_RESULT_RESPONSE, syncResult, commandContext.getChannel()))
|
||||
.thenApply(unused -> CommandResult.fromIgnored());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandConfiguration getConfiguration() {
|
||||
List<Parameter> parameters = new ArrayList<>();
|
||||
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();
|
||||
return CommandConfiguration.builder()
|
||||
.name("syncTrackedEmotes")
|
||||
.module(StatisticModule.STATISTIC)
|
||||
.templated(true)
|
||||
.async(true)
|
||||
.supportsEmbedException(true)
|
||||
.causesReaction(true)
|
||||
.parameters(parameters)
|
||||
.help(helpInfo)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeatureEnum getFeature() {
|
||||
return StatisticFeatures.EMOTE_TRACKING;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
package dev.sheldan.abstracto.statistic.emotes.command;
|
||||
|
||||
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.exception.IncorrectParameterException;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandContext;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.config.FeatureEnum;
|
||||
import dev.sheldan.abstracto.core.exception.IncorrectFeatureModeException;
|
||||
import dev.sheldan.abstracto.core.service.EmoteService;
|
||||
import dev.sheldan.abstracto.core.service.FeatureModeService;
|
||||
import dev.sheldan.abstracto.statistic.config.StatisticFeatures;
|
||||
import dev.sheldan.abstracto.statistic.config.StatisticModule;
|
||||
import dev.sheldan.abstracto.statistic.emotes.command.parameter.TrackEmoteParameter;
|
||||
import dev.sheldan.abstracto.statistic.emotes.config.EmoteTrackingMode;
|
||||
import dev.sheldan.abstracto.statistic.emotes.model.database.TrackedEmote;
|
||||
import dev.sheldan.abstracto.statistic.emotes.service.TrackedEmoteService;
|
||||
import dev.sheldan.abstracto.statistic.emotes.service.management.TrackedEmoteManagementService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
public class TrackEmote extends AbstractConditionableCommand {
|
||||
|
||||
@Autowired
|
||||
private TrackedEmoteService trackedEmoteService;
|
||||
|
||||
@Autowired
|
||||
private TrackedEmoteManagementService trackedEmoteManagementService;
|
||||
|
||||
@Autowired
|
||||
private EmoteService emoteService;
|
||||
|
||||
@Autowired
|
||||
private FeatureModeService featureModeService;
|
||||
|
||||
@Override
|
||||
public CommandResult execute(CommandContext commandContext) {
|
||||
checkParameters(commandContext);
|
||||
TrackEmoteParameter emoteToTrack = (TrackEmoteParameter) commandContext.getParameters().getParameters().get(0);
|
||||
Long emoteId = emoteToTrack.getTrackedEmote().getTrackedEmoteId().getEmoteId();
|
||||
long serverId = commandContext.getGuild().getIdLong();
|
||||
if(trackedEmoteManagementService.trackedEmoteExists(emoteId, serverId)) {
|
||||
TrackedEmote trackedemote = trackedEmoteManagementService.loadByEmoteId(emoteId, serverId);
|
||||
trackedEmoteManagementService.enableTrackedEmote(trackedemote);
|
||||
} else if(emoteToTrack.getEmote() != null) {
|
||||
boolean external = !emoteService.emoteIsFromGuild(emoteToTrack.getEmote(), commandContext.getGuild());
|
||||
if(external) {
|
||||
boolean trackExternalEmotes = featureModeService.featureModeActive(StatisticFeatures.EMOTE_TRACKING, serverId, EmoteTrackingMode.EXTERNAL_EMOTES);
|
||||
if(!trackExternalEmotes) {
|
||||
throw new IncorrectFeatureModeException(StatisticFeatures.EMOTE_TRACKING, Arrays.asList(EmoteTrackingMode.EXTERNAL_EMOTES));
|
||||
}
|
||||
}
|
||||
trackedEmoteService.createFakeTrackedEmote(emoteToTrack.getEmote(), commandContext.getGuild());
|
||||
} else {
|
||||
throw new IncorrectParameterException(this, getConfiguration().getParameters().get(0).getName());
|
||||
}
|
||||
return CommandResult.fromSuccess();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandConfiguration getConfiguration() {
|
||||
List<Parameter> parameters = new ArrayList<>();
|
||||
parameters.add(Parameter.builder().name("emote").templated(true).type(TrackEmoteParameter.class).build());
|
||||
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();
|
||||
return CommandConfiguration.builder()
|
||||
.name("trackEmote")
|
||||
.module(StatisticModule.STATISTIC)
|
||||
.templated(true)
|
||||
.supportsEmbedException(true)
|
||||
.causesReaction(true)
|
||||
.parameters(parameters)
|
||||
.help(helpInfo)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeatureEnum getFeature() {
|
||||
return StatisticFeatures.EMOTE_TRACKING;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package dev.sheldan.abstracto.statistic.emotes.command.parameter;
|
||||
|
||||
import dev.sheldan.abstracto.statistic.emotes.model.database.TrackedEmote;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import net.dv8tion.jda.api.entities.Emote;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@Builder
|
||||
public class TrackEmoteParameter {
|
||||
private Emote emote;
|
||||
private TrackedEmote trackedEmote;
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package dev.sheldan.abstracto.statistic.emotes.command.parameter.handler;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.handler.CommandParameterHandler;
|
||||
import dev.sheldan.abstracto.core.command.handler.CommandParameterIterators;
|
||||
import dev.sheldan.abstracto.core.command.handler.provided.EmoteParameterHandler;
|
||||
import dev.sheldan.abstracto.statistic.emotes.model.database.TrackedEmote;
|
||||
import dev.sheldan.abstracto.statistic.emotes.service.TrackedEmoteService;
|
||||
import net.dv8tion.jda.api.entities.Emote;
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class TrackedEmoteParameterHandler implements CommandParameterHandler {
|
||||
|
||||
@Autowired
|
||||
private EmoteParameterHandler emoteParameterHandler;
|
||||
|
||||
@Autowired
|
||||
private TrackedEmoteService trackedEmoteService;
|
||||
|
||||
@Override
|
||||
public boolean handles(Class clazz) {
|
||||
return clazz.equals(TrackedEmote.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object handle(String input, CommandParameterIterators iterators, Class clazz, Message context) {
|
||||
Emote emote = (Emote) emoteParameterHandler.handle(input, iterators, Emote.class, context);
|
||||
if(emote != null) {
|
||||
return trackedEmoteService.getFakeTrackedEmote(emote, context.getGuild());
|
||||
} else {
|
||||
long trackedEmoteId = Long.parseLong(input);
|
||||
return trackedEmoteService.getFakeTrackedEmote(trackedEmoteId, context.getGuild());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getPriority() {
|
||||
return 51;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package dev.sheldan.abstracto.statistic.emotes.command.parameter.handler;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.handler.CommandParameterHandler;
|
||||
import dev.sheldan.abstracto.core.command.handler.CommandParameterIterators;
|
||||
import dev.sheldan.abstracto.core.command.handler.provided.EmoteParameterHandler;
|
||||
import dev.sheldan.abstracto.statistic.emotes.command.parameter.TrackEmoteParameter;
|
||||
import dev.sheldan.abstracto.statistic.emotes.service.TrackedEmoteService;
|
||||
import net.dv8tion.jda.api.entities.Emote;
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class TrackedEmoteParameterParameterHandler implements CommandParameterHandler {
|
||||
|
||||
@Autowired
|
||||
private EmoteParameterHandler emoteParameterHandler;
|
||||
|
||||
@Autowired
|
||||
private TrackedEmoteService trackedEmoteService;
|
||||
|
||||
@Override
|
||||
public boolean handles(Class clazz) {
|
||||
return clazz.equals(TrackEmoteParameter.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object handle(String input, CommandParameterIterators iterators, Class clazz, Message context) {
|
||||
TrackEmoteParameter parameter = TrackEmoteParameter.builder().build();
|
||||
Emote emote = (Emote) emoteParameterHandler.handle(input, iterators, Emote.class, context);
|
||||
if(emote != null) {
|
||||
parameter.setEmote(emote);
|
||||
parameter.setTrackedEmote(trackedEmoteService.getFakeTrackedEmote(emote, context.getGuild()));
|
||||
} else {
|
||||
long trackedEmoteId = Long.parseLong(input);
|
||||
parameter.setTrackedEmote(trackedEmoteService.getFakeTrackedEmote(trackedEmoteId, context.getGuild()));
|
||||
}
|
||||
return parameter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getPriority() {
|
||||
return 51;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package dev.sheldan.abstracto.statistic.emotes.converter;
|
||||
|
||||
import dev.sheldan.abstracto.core.service.BotService;
|
||||
import dev.sheldan.abstracto.statistic.emotes.model.EmoteStatsModel;
|
||||
import dev.sheldan.abstracto.statistic.emotes.model.EmoteStatsResult;
|
||||
import dev.sheldan.abstracto.statistic.emotes.model.EmoteStatsResultDisplay;
|
||||
import dev.sheldan.abstracto.statistic.emotes.model.database.TrackedEmote;
|
||||
import dev.sheldan.abstracto.statistic.emotes.service.management.TrackedEmoteManagementService;
|
||||
import net.dv8tion.jda.api.entities.Emote;
|
||||
import net.dv8tion.jda.api.entities.Guild;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
public class EmoteStatsConverter {
|
||||
|
||||
@Autowired
|
||||
private BotService botService;
|
||||
|
||||
@Autowired
|
||||
private TrackedEmoteManagementService trackedEmoteManagementService;
|
||||
|
||||
public EmoteStatsModel fromEmoteStatsResults(List<EmoteStatsResult> resultList) {
|
||||
if(resultList.isEmpty()) {
|
||||
return EmoteStatsModel.builder().build();
|
||||
}
|
||||
Guild relevantGuild = botService.getGuildById(resultList.get(0).getServerId());
|
||||
EmoteStatsModel resultingModel = EmoteStatsModel.builder().build();
|
||||
resultList.forEach(emoteStatsResult -> {
|
||||
TrackedEmote trackedEmote = trackedEmoteManagementService.loadByEmoteId(emoteStatsResult.getEmoteId(), emoteStatsResult.getServerId());
|
||||
Emote loadedEmote = null;
|
||||
if(!trackedEmote.getExternal() && !trackedEmote.getDeleted()) {
|
||||
loadedEmote = relevantGuild.getEmoteById(trackedEmote.getTrackedEmoteId().getEmoteId());
|
||||
}
|
||||
EmoteStatsResultDisplay display = EmoteStatsResultDisplay
|
||||
.builder()
|
||||
.emote(loadedEmote)
|
||||
.result(emoteStatsResult)
|
||||
.trackedEmote(trackedEmote)
|
||||
.build();
|
||||
if(display.getTrackedEmote().getAnimated()) {
|
||||
resultingModel.getAnimatedEmotes().add(display);
|
||||
} else {
|
||||
resultingModel.getStaticEmotes().add(display);
|
||||
}
|
||||
});
|
||||
return resultingModel;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package dev.sheldan.abstracto.statistic.emotes.job;
|
||||
|
||||
import dev.sheldan.abstracto.statistic.emotes.model.PersistingEmote;
|
||||
import dev.sheldan.abstracto.statistic.emotes.service.TrackedEmoteRuntimeService;
|
||||
import dev.sheldan.abstracto.statistic.emotes.service.TrackedEmoteService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.quartz.DisallowConcurrentExecution;
|
||||
import org.quartz.JobExecutionContext;
|
||||
import org.quartz.JobExecutionException;
|
||||
import org.quartz.PersistJobDataAfterExecution;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.scheduling.quartz.QuartzJobBean;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Slf4j
|
||||
@DisallowConcurrentExecution
|
||||
@Component
|
||||
@PersistJobDataAfterExecution
|
||||
public class EmotePersistingJob extends QuartzJobBean {
|
||||
|
||||
@Autowired
|
||||
private TrackedEmoteRuntimeService trackedEmoteRuntimeService;
|
||||
|
||||
@Autowired
|
||||
private TrackedEmoteService trackedEmoteService;
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
|
||||
Map<Long, Map<Long, List<PersistingEmote>>> runtimeConfig = trackedEmoteRuntimeService.getRuntimeConfig();
|
||||
log.info("Running statistic persisting job.");
|
||||
Long pastMinute = getPastMinute();
|
||||
if(runtimeConfig.containsKey(pastMinute)) {
|
||||
Map<Long, List<PersistingEmote>> foundStatistics = runtimeConfig.get(pastMinute);
|
||||
log.info("Found emote statistics from {} servers to persist.", foundStatistics.size());
|
||||
trackedEmoteService.storeEmoteStatistics(foundStatistics);
|
||||
runtimeConfig.remove(pastMinute);
|
||||
checkForPastEmoteStats(pastMinute, runtimeConfig);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkForPastEmoteStats(Long minuteToCheck, Map<Long, Map<Long, List<PersistingEmote>>> runtimeConfig) {
|
||||
List<Long> missedMinutes = runtimeConfig.keySet().stream().filter(aLong -> aLong < minuteToCheck).collect(Collectors.toList());
|
||||
missedMinutes.forEach(pastMinute -> {
|
||||
log.info("Persisting emotes for a minute in the past, it should have been previously, but was not. Minute {}.", pastMinute);
|
||||
trackedEmoteService.storeEmoteStatistics(runtimeConfig.get(pastMinute));
|
||||
runtimeConfig.remove(pastMinute);
|
||||
});
|
||||
}
|
||||
|
||||
public long getPastMinute() {
|
||||
return (Instant.now().getEpochSecond() / 60) - 1;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package dev.sheldan.abstracto.statistic.emotes.listener;
|
||||
|
||||
import dev.sheldan.abstracto.core.config.FeatureEnum;
|
||||
import dev.sheldan.abstracto.core.config.ListenerPriority;
|
||||
import dev.sheldan.abstracto.core.listener.EmoteCreatedListener;
|
||||
import dev.sheldan.abstracto.statistic.config.StatisticFeatures;
|
||||
import dev.sheldan.abstracto.statistic.emotes.service.management.TrackedEmoteManagementService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.dv8tion.jda.api.entities.Emote;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class CreateTrackedEmoteListener implements EmoteCreatedListener {
|
||||
|
||||
@Autowired
|
||||
private TrackedEmoteManagementService trackedEmoteManagementService;
|
||||
|
||||
@Override
|
||||
public void emoteCreated(Emote createdEmote) {
|
||||
// guild should be available, because we are in the emote created event, and the emote object should come from there
|
||||
log.info("Creating tracked emote {} in server {}.", createdEmote.getGuild().getIdLong(), createdEmote.getIdLong());
|
||||
trackedEmoteManagementService.createTrackedEmote(createdEmote, createdEmote.getGuild());
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeatureEnum getFeature() {
|
||||
return StatisticFeatures.EMOTE_TRACKING;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getPriority() {
|
||||
return ListenerPriority.MEDIUM;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package dev.sheldan.abstracto.statistic.emotes.listener;
|
||||
|
||||
import dev.sheldan.abstracto.core.config.FeatureEnum;
|
||||
import dev.sheldan.abstracto.core.config.ListenerPriority;
|
||||
import dev.sheldan.abstracto.core.listener.EmoteDeletedListener;
|
||||
import dev.sheldan.abstracto.statistic.config.StatisticFeatures;
|
||||
import dev.sheldan.abstracto.statistic.emotes.service.management.TrackedEmoteManagementService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.dv8tion.jda.api.entities.Emote;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class DeleteTrackedEmoteListener implements EmoteDeletedListener {
|
||||
|
||||
@Autowired
|
||||
private TrackedEmoteManagementService trackedEmoteManagementService;
|
||||
|
||||
@Override
|
||||
public void emoteDeleted(Emote deletedEmote) {
|
||||
log.info("Marking tracked emote {} in gild {} as deleted.", deletedEmote.getId(), deletedEmote.getGuild().getIdLong());
|
||||
trackedEmoteManagementService.markAsDeleted(deletedEmote.getGuild().getIdLong(), deletedEmote.getIdLong());
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeatureEnum getFeature() {
|
||||
return StatisticFeatures.EMOTE_TRACKING;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getPriority() {
|
||||
return ListenerPriority.MEDIUM;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package dev.sheldan.abstracto.statistic.emotes.listener;
|
||||
|
||||
import dev.sheldan.abstracto.core.config.FeatureEnum;
|
||||
import dev.sheldan.abstracto.core.config.ListenerPriority;
|
||||
import dev.sheldan.abstracto.core.listener.MessageReceivedListener;
|
||||
import dev.sheldan.abstracto.statistic.config.StatisticFeatures;
|
||||
import dev.sheldan.abstracto.statistic.emotes.service.TrackedEmoteService;
|
||||
import net.dv8tion.jda.api.entities.Emote;
|
||||
import net.dv8tion.jda.api.entities.ISnowflake;
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
import org.apache.commons.collections4.Bag;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Component
|
||||
public class EmoteTrackingListener implements MessageReceivedListener {
|
||||
|
||||
@Autowired
|
||||
private TrackedEmoteService trackedEmoteService;
|
||||
|
||||
@Override
|
||||
public void execute(Message message) {
|
||||
Bag<Emote> emotesBag = message.getEmotesBag();
|
||||
Map<Long, List<Emote>> collect = emotesBag.stream().collect(Collectors.groupingBy(ISnowflake::getIdLong));
|
||||
collect.values().forEach(groupedEmotes ->
|
||||
trackedEmoteService.addEmoteToRuntimeStorage(groupedEmotes.get(0), message.getGuild(), (long) groupedEmotes.size())
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeatureEnum getFeature() {
|
||||
return StatisticFeatures.EMOTE_TRACKING;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getPriority() {
|
||||
return ListenerPriority.LOW;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package dev.sheldan.abstracto.statistic.emotes.listener;
|
||||
|
||||
import dev.sheldan.abstracto.core.config.FeatureEnum;
|
||||
import dev.sheldan.abstracto.core.config.ListenerPriority;
|
||||
import dev.sheldan.abstracto.core.listener.EmoteUpdatedListener;
|
||||
import dev.sheldan.abstracto.statistic.config.StatisticFeatures;
|
||||
import dev.sheldan.abstracto.statistic.emotes.model.database.TrackedEmote;
|
||||
import dev.sheldan.abstracto.statistic.emotes.service.management.TrackedEmoteManagementService;
|
||||
import net.dv8tion.jda.api.entities.Emote;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class UpdateTrackedEmoteListener implements EmoteUpdatedListener {
|
||||
|
||||
@Autowired
|
||||
private TrackedEmoteManagementService trackedEmoteManagementService;
|
||||
|
||||
@Override
|
||||
public void emoteUpdated(Emote updatedEmote, String oldValue, String newValue) {
|
||||
TrackedEmote trackedEmote = trackedEmoteManagementService.loadByEmote(updatedEmote);
|
||||
trackedEmoteManagementService.changeName(trackedEmote, newValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeatureEnum getFeature() {
|
||||
return StatisticFeatures.EMOTE_TRACKING;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getPriority() {
|
||||
return ListenerPriority.MEDIUM;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package dev.sheldan.abstracto.statistic.emotes.model;
|
||||
|
||||
import dev.sheldan.abstracto.statistic.emotes.model.database.UsedEmote;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import net.dv8tion.jda.api.entities.Guild;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.List;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@Builder
|
||||
public class DownloadEmoteStatsModel {
|
||||
private Guild guild;
|
||||
private Instant downloadDate;
|
||||
private Instant statsSince;
|
||||
private Member requester;
|
||||
private List<UsedEmote> emotes;
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package dev.sheldan.abstracto.statistic.emotes.repository;
|
||||
|
||||
import dev.sheldan.abstracto.statistic.emotes.model.database.TrackedEmote;
|
||||
import dev.sheldan.abstracto.statistic.emotes.model.database.embed.TrackedEmoteServer;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.QueryHints;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import javax.persistence.QueryHint;
|
||||
import java.util.List;
|
||||
|
||||
@Repository
|
||||
public interface TrackedEmoteRepository extends JpaRepository<TrackedEmote, TrackedEmoteServer> {
|
||||
@QueryHints(@QueryHint(name = org.hibernate.annotations.QueryHints.CACHEABLE, value = "true"))
|
||||
List<TrackedEmote> findByTrackedEmoteId_ServerIdAndDeletedFalseAndExternalFalse(Long serverId);
|
||||
|
||||
@QueryHints(@QueryHint(name = org.hibernate.annotations.QueryHints.CACHEABLE, value = "true"))
|
||||
List<TrackedEmote> findByTrackedEmoteId_ServerIdAndTrackingEnabledTrue(Long serverId);
|
||||
|
||||
@QueryHints(@QueryHint(name = org.hibernate.annotations.QueryHints.CACHEABLE, value = "true"))
|
||||
List<TrackedEmote> findByTrackedEmoteId_ServerId(Long serverId);
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package dev.sheldan.abstracto.statistic.emotes.repository;
|
||||
|
||||
import dev.sheldan.abstracto.statistic.emotes.model.EmoteStatsResult;
|
||||
import dev.sheldan.abstracto.statistic.emotes.model.database.UsedEmote;
|
||||
import dev.sheldan.abstracto.statistic.emotes.model.database.embed.UsedEmoteDay;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@Repository
|
||||
public interface UsedEmoteRepository extends JpaRepository<UsedEmote, UsedEmoteDay> {
|
||||
|
||||
@Query(value="select * from used_emote " +
|
||||
"where emote_id = :emote_id and server_id = :server_id " +
|
||||
"and use_date = date_trunc('day', now())", nativeQuery = true)
|
||||
Optional<UsedEmote> findEmoteFromServerToday(@Param("emote_id") Long emoteId, @Param("server_id") Long server_id);
|
||||
|
||||
@Query(value = "select us.emote_id as emoteId, us.server_id as serverId, sum(us.amount) as amount from used_emote us " +
|
||||
"inner join tracked_emote te " +
|
||||
"on us.emote_id = te.id and us.server_id = te.server_id " +
|
||||
"where us.use_date >= date_trunc('day', cast(:start_date AS timestamp)) and us.server_id = :server_id " +
|
||||
"group by us.emote_id, us.server_id " +
|
||||
"order by amount desc", nativeQuery = true)
|
||||
List<EmoteStatsResult> getEmoteStatsForServerSince(@Param("server_id") Long serverId, @Param("start_date") Instant since);
|
||||
|
||||
@Query(value = "select us.emote_id as emoteId, us.server_id as serverId, sum(us.amount) as amount from used_emote us " +
|
||||
"inner join tracked_emote te " +
|
||||
"on us.emote_id = te.id and us.server_id = te.server_id " +
|
||||
"where us.use_date >= date_trunc('day', cast(:start_date AS timestamp)) and us.server_id = :server_id and te.external = true " +
|
||||
"group by us.emote_id, us.server_id " +
|
||||
"order by amount desc", nativeQuery = true)
|
||||
List<EmoteStatsResult> getExternalEmoteStatsForServerSince(@Param("server_id") Long serverId, @Param("start_date") Instant since);
|
||||
|
||||
@Query(value = "select us.emote_id as emoteId, us.server_id as serverId, sum(us.amount) as amount from used_emote us " +
|
||||
"inner join tracked_emote te " +
|
||||
"on us.emote_id = te.id and us.server_id = te.server_id " +
|
||||
"where us.use_date >= date_trunc('day', cast(:start_date AS timestamp)) and us.server_id = :server_id and te.deleted = true " +
|
||||
"group by us.emote_id, us.server_id " +
|
||||
"order by amount desc", nativeQuery = true)
|
||||
List<EmoteStatsResult> getDeletedEmoteStatsForServerSince(@Param("server_id") Long serverId, @Param("start_date") Instant since);
|
||||
|
||||
@Query(value = "select us.emote_id as emoteId, us.server_id as serverId, sum(us.amount) as amount from used_emote us " +
|
||||
"inner join tracked_emote te " +
|
||||
"on us.emote_id = te.id and us.server_id = te.server_id " +
|
||||
"where us.use_date >= date_trunc('day', cast(:start_date AS timestamp)) and us.server_id = :server_id and te.external = false and te.deleted = false " +
|
||||
"group by us.emote_id, us.server_id " +
|
||||
"order by amount desc", nativeQuery = true)
|
||||
List<EmoteStatsResult> getCurrentlyExistingEmoteStatsForServerSince(@Param("server_id") Long serverId, @Param("start_date") Instant since);
|
||||
|
||||
void deleteByEmoteId_EmoteIdAndEmoteId_ServerIdAndEmoteId_UseDateGreaterThan(Long emoteId, Long serverId, Instant timestamp);
|
||||
|
||||
List<UsedEmote> getByEmoteId_ServerIdAndEmoteId_UseDateGreaterThan(Long emoteId, Instant timestamp);
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package dev.sheldan.abstracto.statistic.emotes.service;
|
||||
|
||||
import dev.sheldan.abstracto.statistic.emotes.model.PersistingEmote;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Component
|
||||
public class TrackedEmoteRunTimeStorage {
|
||||
private HashMap<Long, Map<Long, List<PersistingEmote>>> trackedEmotes = new HashMap<>();
|
||||
|
||||
public Map<Long, Map<Long, List<PersistingEmote>>> getRuntimeConfig() {
|
||||
return trackedEmotes;
|
||||
}
|
||||
|
||||
public boolean contains(Long key) {
|
||||
return trackedEmotes.containsKey(key);
|
||||
}
|
||||
|
||||
public void put(Long key, Map<Long, List<PersistingEmote>> objectToPut) {
|
||||
trackedEmotes.put(key, objectToPut);
|
||||
}
|
||||
|
||||
public Map<Long, List<PersistingEmote>> get(Long key) {
|
||||
return trackedEmotes.get(key);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
package dev.sheldan.abstracto.statistic.emotes.service;
|
||||
|
||||
import dev.sheldan.abstracto.statistic.emotes.model.PersistingEmote;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.dv8tion.jda.api.entities.Emote;
|
||||
import net.dv8tion.jda.api.entities.Guild;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.*;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class TrackedEmoteRuntimeServiceBean implements TrackedEmoteRuntimeService {
|
||||
|
||||
@Autowired
|
||||
private TrackedEmoteRunTimeStorage trackedEmoteRunTimeStorage;
|
||||
|
||||
@Override
|
||||
public Map<Long, Map<Long, List<PersistingEmote>>> getRuntimeConfig() {
|
||||
return trackedEmoteRunTimeStorage.getRuntimeConfig();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addEmoteForServer(Emote emote, Guild guild, boolean external) {
|
||||
addEmoteForServer(emote, guild, 1L, external);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addEmoteForServer(Emote emote, Guild guild, Long count, boolean external) {
|
||||
Long key = getKey();
|
||||
PersistingEmote newPersistentEmote = createFromEmote(guild, emote, count, external);
|
||||
if(trackedEmoteRunTimeStorage.contains(key)) {
|
||||
Map<Long, List<PersistingEmote>> elementsForKey = trackedEmoteRunTimeStorage.get(key);
|
||||
if(elementsForKey.containsKey(guild.getIdLong())) {
|
||||
List<PersistingEmote> persistingEmotes = elementsForKey.get(guild.getIdLong());
|
||||
Optional<PersistingEmote> existingEmote = persistingEmotes
|
||||
.stream()
|
||||
.filter(persistingEmote -> persistingEmote.getEmoteId().equals(emote.getIdLong()))
|
||||
.findFirst();
|
||||
existingEmote.ifPresent(persistingEmote -> persistingEmote.setCount(persistingEmote.getCount() + count));
|
||||
if(!existingEmote.isPresent()) {
|
||||
persistingEmotes.add(newPersistentEmote);
|
||||
}
|
||||
} else {
|
||||
log.trace("Adding emote {} to list of server {}.", newPersistentEmote.getEmoteId(), guild.getIdLong());
|
||||
elementsForKey.put(guild.getIdLong(), new ArrayList<>(Arrays.asList(newPersistentEmote)));
|
||||
}
|
||||
} else {
|
||||
HashMap<Long, List<PersistingEmote>> serverEmotes = new HashMap<>();
|
||||
serverEmotes.put(guild.getIdLong(), new ArrayList<>(Arrays.asList(newPersistentEmote)));
|
||||
log.trace("Adding emote map entry for server {}.", guild.getIdLong());
|
||||
trackedEmoteRunTimeStorage.put(key, serverEmotes);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long getKey() {
|
||||
return Instant.now().getEpochSecond() / 60;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PersistingEmote createFromEmote(Guild guild, Emote emote, boolean external) {
|
||||
return createFromEmote(guild, emote, 1L, external);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PersistingEmote createFromEmote(Guild guild, Emote emote, Long count, boolean external) {
|
||||
String url = external ? emote.getImageUrl() : null;
|
||||
return PersistingEmote
|
||||
.builder()
|
||||
.animated(emote.isAnimated())
|
||||
.emoteId(emote.getIdLong())
|
||||
.external(external)
|
||||
.externalUrl(url)
|
||||
.emoteName(emote.getName())
|
||||
.count(count)
|
||||
.serverId(guild.getIdLong())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,197 @@
|
||||
package dev.sheldan.abstracto.statistic.emotes.service;
|
||||
|
||||
import dev.sheldan.abstracto.core.service.BotService;
|
||||
import dev.sheldan.abstracto.core.service.EmoteService;
|
||||
import dev.sheldan.abstracto.core.service.FeatureModeService;
|
||||
import dev.sheldan.abstracto.statistic.config.StatisticFeatures;
|
||||
import dev.sheldan.abstracto.statistic.emotes.config.EmoteTrackingMode;
|
||||
import dev.sheldan.abstracto.statistic.emotes.model.PersistingEmote;
|
||||
import dev.sheldan.abstracto.statistic.emotes.model.TrackedEmoteOverview;
|
||||
import dev.sheldan.abstracto.statistic.emotes.model.TrackedEmoteSynchronizationResult;
|
||||
import dev.sheldan.abstracto.statistic.emotes.model.database.TrackedEmote;
|
||||
import dev.sheldan.abstracto.statistic.emotes.model.database.UsedEmote;
|
||||
import dev.sheldan.abstracto.statistic.emotes.model.database.embed.TrackedEmoteServer;
|
||||
import dev.sheldan.abstracto.statistic.emotes.service.management.TrackedEmoteManagementService;
|
||||
import dev.sheldan.abstracto.statistic.emotes.service.management.UsedEmoteManagementService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.dv8tion.jda.api.entities.Emote;
|
||||
import net.dv8tion.jda.api.entities.Guild;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.Map;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class TrackedEmoteServiceBean implements TrackedEmoteService {
|
||||
|
||||
@Autowired
|
||||
private TrackedEmoteRuntimeService trackedEmoteRuntimeService;
|
||||
|
||||
@Autowired
|
||||
private FeatureModeService featureModeService;
|
||||
|
||||
@Autowired
|
||||
private EmoteService emoteService;
|
||||
|
||||
@Autowired
|
||||
private TrackedEmoteManagementService trackedEmoteManagementService;
|
||||
|
||||
@Autowired
|
||||
private UsedEmoteManagementService usedEmoteManagementService;
|
||||
|
||||
@Autowired
|
||||
private BotService botService;
|
||||
|
||||
@Override
|
||||
public void addEmoteToRuntimeStorage(List<Emote> emotes, Guild guild) {
|
||||
boolean externalTrackingEnabled = featureModeService.featureModeActive(StatisticFeatures.EMOTE_TRACKING, guild.getIdLong(), EmoteTrackingMode.EXTERNAL_EMOTES);
|
||||
emotes.forEach(emote -> {
|
||||
boolean emoteIsFromGuild = emoteService.emoteIsFromGuild(emote, guild);
|
||||
if(externalTrackingEnabled || emoteIsFromGuild) {
|
||||
trackedEmoteRuntimeService.addEmoteForServer(emote, guild, !emoteIsFromGuild);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addEmoteToRuntimeStorage(Emote emote, Guild guild, Long count) {
|
||||
boolean externalTrackingEnabled = featureModeService.featureModeActive(StatisticFeatures.EMOTE_TRACKING, guild.getIdLong(), EmoteTrackingMode.EXTERNAL_EMOTES);
|
||||
boolean emoteIsFromGuild = emoteService.emoteIsFromGuild(emote, guild);
|
||||
if(externalTrackingEnabled || emoteIsFromGuild) {
|
||||
trackedEmoteRuntimeService.addEmoteForServer(emote, guild, count, !emoteIsFromGuild);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void storeEmoteStatistics(Map<Long, List<PersistingEmote>> usagesToStore) {
|
||||
usagesToStore.forEach((serverId, persistingEmotes) -> {
|
||||
log.info("Storing {} emotes for server {}.", persistingEmotes.size(), serverId);
|
||||
boolean autoTrackExternalEmotes = featureModeService.featureModeActive(StatisticFeatures.EMOTE_TRACKING, serverId, EmoteTrackingMode.AUTO_TRACK_EXTERNAL);
|
||||
boolean trackExternalEmotes = featureModeService.featureModeActive(StatisticFeatures.EMOTE_TRACKING, serverId, EmoteTrackingMode.EXTERNAL_EMOTES);
|
||||
persistingEmotes.forEach(persistingEmote -> {
|
||||
Optional<TrackedEmote> emoteOptional = trackedEmoteManagementService.loadByEmoteIdOptional(persistingEmote.getEmoteId(), serverId);
|
||||
emoteOptional.ifPresent(trackedEmote -> {
|
||||
if(trackedEmote.getTrackingEnabled()) {
|
||||
Optional<UsedEmote> existingUsedEmote = usedEmoteManagementService.loadUsedEmoteForTrackedEmoteToday(trackedEmote);
|
||||
existingUsedEmote.ifPresent(usedEmote ->
|
||||
usedEmote.setAmount(usedEmote.getAmount() + persistingEmote.getCount())
|
||||
);
|
||||
if(!existingUsedEmote.isPresent()) {
|
||||
usedEmoteManagementService.createEmoteUsageForToday(trackedEmote, persistingEmote.getCount());
|
||||
}
|
||||
} else {
|
||||
log.trace("Tracking disabled for emote {} in server {}.", trackedEmote.getTrackedEmoteId().getEmoteId(), trackedEmote.getTrackedEmoteId().getServerId());
|
||||
}
|
||||
});
|
||||
if(!emoteOptional.isPresent()) {
|
||||
createNewTrackedEmote(serverId, autoTrackExternalEmotes, trackExternalEmotes, persistingEmote);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private void createNewTrackedEmote(Long serverId, boolean autoTrackExternalEmotes, boolean trackExternalEmotes, PersistingEmote persistingEmote) {
|
||||
Optional<Guild> guildOptional = botService.getGuildByIdOptional(serverId);
|
||||
guildOptional.ifPresent(guild -> {
|
||||
Emote emoteFromGuild = guild.getEmoteById(persistingEmote.getEmoteId());
|
||||
if(emoteFromGuild != null) {
|
||||
TrackedEmote newCreatedTrackedEmote = trackedEmoteManagementService.createTrackedEmote(emoteFromGuild, guild);
|
||||
usedEmoteManagementService.createEmoteUsageForToday(newCreatedTrackedEmote, persistingEmote.getCount());
|
||||
} else if(autoTrackExternalEmotes && trackExternalEmotes){
|
||||
TrackedEmote newCreatedTrackedEmote = trackedEmoteManagementService.createExternalEmote(persistingEmote);
|
||||
usedEmoteManagementService.createEmoteUsageForToday(newCreatedTrackedEmote, persistingEmote.getCount());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public TrackedEmote getFakeTrackedEmote(Emote emote, Guild guild) {
|
||||
return getFakeTrackedEmote(emote.getIdLong(), guild);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TrackedEmote getFakeTrackedEmote(Long id, Guild guild) {
|
||||
return TrackedEmote
|
||||
.builder()
|
||||
.trackedEmoteId(new TrackedEmoteServer(id, guild.getIdLong()))
|
||||
.fake(true)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TrackedEmoteSynchronizationResult synchronizeTrackedEmotes(Guild guild) {
|
||||
List<TrackedEmote> activeTrackedEmotes = trackedEmoteManagementService.getAllActiveTrackedEmoteForServer(guild.getIdLong());
|
||||
Long addedEmotes = 0L;
|
||||
List<Emote> allExistingEmotes = guild.getEmotes();
|
||||
log.info("Synchronizing emotes for server {}, currently tracked emotes {}, available emotes for server {}.", guild.getIdLong(), activeTrackedEmotes.size(), allExistingEmotes.size());
|
||||
for (Emote emote : allExistingEmotes) {
|
||||
Optional<TrackedEmote> trackedEmoteOptional = activeTrackedEmotes
|
||||
.stream()
|
||||
.filter(trackedEmote ->
|
||||
trackedEmote.getTrackedEmoteId().getEmoteId().equals(emote.getIdLong())
|
||||
&& trackedEmote.getTrackedEmoteId().getServerId().equals(guild.getIdLong()))
|
||||
.findFirst();
|
||||
if (!trackedEmoteOptional.isPresent()) {
|
||||
trackedEmoteManagementService.createTrackedEmote(emote, guild);
|
||||
addedEmotes++;
|
||||
} else {
|
||||
activeTrackedEmotes.remove(trackedEmoteOptional.get());
|
||||
}
|
||||
}
|
||||
|
||||
activeTrackedEmotes.forEach(trackedEmote ->
|
||||
trackedEmoteManagementService.markAsDeleted(trackedEmote)
|
||||
);
|
||||
return TrackedEmoteSynchronizationResult
|
||||
.builder()
|
||||
.emotesAdded(addedEmotes)
|
||||
.emotesMarkedDeleted((long) activeTrackedEmotes.size())
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TrackedEmoteOverview loadTrackedEmoteOverview(Guild guild) {
|
||||
return loadTrackedEmoteOverview(guild, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TrackedEmoteOverview loadTrackedEmoteOverview(Guild guild, Boolean showTrackingDisabled) {
|
||||
List<TrackedEmote> trackedEmotes = trackedEmoteManagementService.getTrackedEmoteForServer(guild.getIdLong(), showTrackingDisabled);
|
||||
TrackedEmoteOverview emoteOverView = TrackedEmoteOverview.builder().build();
|
||||
trackedEmotes.forEach(trackedEmote ->
|
||||
emoteOverView.addTrackedEmote(trackedEmote, guild)
|
||||
);
|
||||
return emoteOverView;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TrackedEmote createFakeTrackedEmote(Emote emote, Guild guild) {
|
||||
boolean external = !emoteService.emoteIsFromGuild(emote, guild);
|
||||
return trackedEmoteManagementService.createTrackedEmote(emote, guild, external);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteTrackedEmote(TrackedEmote trackedEmote) {
|
||||
usedEmoteManagementService.purgeEmoteUsagesSince(trackedEmote, Instant.EPOCH);
|
||||
trackedEmoteManagementService.deleteTrackedEmote(trackedEmote);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetEmoteStats(Guild guild) {
|
||||
List<TrackedEmote> trackedEmotes = trackedEmoteManagementService.getTrackedEmoteForServer(guild.getIdLong(), true);
|
||||
trackedEmotes.forEach(this::deleteTrackedEmote);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disableEmoteTracking(Guild guild) {
|
||||
List<TrackedEmote> trackedEmotes = trackedEmoteManagementService.getTrackedEmoteForServer(guild.getIdLong(), true);
|
||||
trackedEmotes.forEach(trackedEmote -> trackedEmote.setTrackingEnabled(false));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package dev.sheldan.abstracto.statistic.emotes.service;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import dev.sheldan.abstracto.statistic.emotes.converter.EmoteStatsConverter;
|
||||
import dev.sheldan.abstracto.statistic.emotes.model.EmoteStatsModel;
|
||||
import dev.sheldan.abstracto.statistic.emotes.model.EmoteStatsResult;
|
||||
import dev.sheldan.abstracto.statistic.emotes.model.database.TrackedEmote;
|
||||
import dev.sheldan.abstracto.statistic.emotes.service.management.UsedEmoteManagementService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class UsedEmoteServiceBean implements UsedEmoteService {
|
||||
|
||||
@Autowired
|
||||
private EmoteStatsConverter converter;
|
||||
|
||||
@Autowired
|
||||
private UsedEmoteManagementService usedEmoteManagementService;
|
||||
|
||||
@Override
|
||||
public EmoteStatsModel getEmoteStatsForServerSince(AServer server, Instant since) {
|
||||
List<EmoteStatsResult> emoteStatsResults = usedEmoteManagementService.loadAllEmoteStatsForServerSince(server, since);
|
||||
return converter.fromEmoteStatsResults(emoteStatsResults);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EmoteStatsModel getDeletedEmoteStatsForServerSince(AServer server, Instant since) {
|
||||
List<EmoteStatsResult> emoteStatsResults = usedEmoteManagementService.loadDeletedEmoteStatsForServerSince(server, since);
|
||||
return converter.fromEmoteStatsResults(emoteStatsResults);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EmoteStatsModel getExternalEmoteStatsForServerSince(AServer server, Instant since) {
|
||||
List<EmoteStatsResult> emoteStatsResults = usedEmoteManagementService.loadExternalEmoteStatsForServerSince(server, since);
|
||||
return converter.fromEmoteStatsResults(emoteStatsResults);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EmoteStatsModel getActiveEmoteStatsForServerSince(AServer server, Instant since) {
|
||||
List<EmoteStatsResult> emoteStatsResults = usedEmoteManagementService.loadActiveEmoteStatsForServerSince(server, since);
|
||||
return converter.fromEmoteStatsResults(emoteStatsResults);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void purgeEmoteUsagesSince(TrackedEmote emote, Instant since) {
|
||||
log.info("Purging emote {} in server {} since {}.", emote.getTrackedEmoteId().getEmoteId(), emote.getTrackedEmoteId().getServerId(), since);
|
||||
usedEmoteManagementService.purgeEmoteUsagesSince(emote, since.truncatedTo(ChronoUnit.DAYS));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void purgeEmoteUsages(TrackedEmote emote) {
|
||||
purgeEmoteUsagesSince(emote, Instant.EPOCH);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,179 @@
|
||||
package dev.sheldan.abstracto.statistic.emotes.service.management;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import dev.sheldan.abstracto.core.service.management.ServerManagementService;
|
||||
import dev.sheldan.abstracto.statistic.emotes.exception.TrackedEmoteNotFoundException;
|
||||
import dev.sheldan.abstracto.statistic.emotes.model.PersistingEmote;
|
||||
import dev.sheldan.abstracto.statistic.emotes.model.database.TrackedEmote;
|
||||
import dev.sheldan.abstracto.statistic.emotes.model.database.embed.TrackedEmoteServer;
|
||||
import dev.sheldan.abstracto.statistic.emotes.repository.TrackedEmoteRepository;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.dv8tion.jda.api.entities.Emote;
|
||||
import net.dv8tion.jda.api.entities.Guild;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class TrackedEmoteManagementServiceBean implements TrackedEmoteManagementService {
|
||||
|
||||
@Autowired
|
||||
private TrackedEmoteRepository repository;
|
||||
|
||||
@Autowired
|
||||
private ServerManagementService serverManagementService;
|
||||
|
||||
@Override
|
||||
public TrackedEmote createTrackedEmote(Long emoteId, String emoteName, Boolean animated, AServer server) {
|
||||
return createTrackedEmote(emoteId, emoteName, animated, true, server);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TrackedEmote createTrackedEmote(Emote emote, Guild guild) {
|
||||
AServer server = serverManagementService.loadServer(guild.getIdLong());
|
||||
return createTrackedEmote(emote.getIdLong(), emote.getName(), emote.isAnimated(), true, server);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TrackedEmote createTrackedEmote(Emote emote, Guild guild, boolean external) {
|
||||
if(external) {
|
||||
return createExternalEmote(emote, guild);
|
||||
} else {
|
||||
return createTrackedEmote(emote, guild);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public TrackedEmote createTrackedEmote(Long emoteId, String emoteName, Boolean animated, Boolean tracked, AServer server) {
|
||||
TrackedEmote emote = TrackedEmote
|
||||
.builder()
|
||||
.animated(animated)
|
||||
.trackedEmoteId(new TrackedEmoteServer(emoteId, server.getId()))
|
||||
.trackingEnabled(tracked)
|
||||
.emoteName(emoteName)
|
||||
.server(server)
|
||||
.external(false)
|
||||
.deleted(false)
|
||||
.build();
|
||||
log.info("Creating tracking emote with id {} and server {}.", emoteId, server.getId());
|
||||
return repository.save(emote);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TrackedEmote createExternalEmote(Long emoteId, String emoteName, String externalUrl, Boolean animated, AServer server) {
|
||||
TrackedEmote emote = TrackedEmote
|
||||
.builder()
|
||||
.animated(animated)
|
||||
.trackedEmoteId(new TrackedEmoteServer(emoteId, server.getId()))
|
||||
.trackingEnabled(true)
|
||||
.deleted(false)
|
||||
.emoteName(emoteName)
|
||||
.server(server)
|
||||
.external(true)
|
||||
.externalUrl(externalUrl)
|
||||
.build();
|
||||
log.info("Creating external emote with id {} for server {}.", emoteId, server.getId());
|
||||
return repository.save(emote);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TrackedEmote createNotTrackedEmote(Long emoteId, String emoteName, Boolean animated, AServer server) {
|
||||
return createTrackedEmote(emoteId, emoteName, animated, false, server);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TrackedEmote createExternalEmote(PersistingEmote persistingEmote) {
|
||||
AServer server = serverManagementService.loadServer(persistingEmote.getServerId());
|
||||
return createExternalEmote(persistingEmote.getEmoteId(), persistingEmote.getEmoteName(), persistingEmote.getExternalUrl(), persistingEmote.getAnimated(), server);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TrackedEmote createExternalEmote(Emote emote, Guild guild) {
|
||||
AServer server = serverManagementService.loadServer(guild.getIdLong());
|
||||
return createExternalEmote(emote.getIdLong(), emote.getName(), emote.getImageUrl(), emote.isAnimated(), server);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void markAsDeleted(Long serverId, Long emoteId) {
|
||||
TrackedEmote emote = loadByEmoteId(emoteId, serverId);
|
||||
markAsDeleted(emote);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void markAsDeleted(TrackedEmote trackedemote) {
|
||||
log.info("Marking tracked emote {} in server {} as deleted.", trackedemote.getTrackedEmoteId().getEmoteId(), trackedemote.getTrackedEmoteId().getServerId());
|
||||
trackedemote.setDeleted(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TrackedEmote loadByEmoteId(Long emoteId, Long serverId) {
|
||||
return loadByEmoteIdOptional(emoteId, serverId).orElseThrow(() -> new TrackedEmoteNotFoundException(String.format("Tracked emote %s in server %s not found.", emoteId, serverId)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public TrackedEmote loadByEmote(Emote emote) {
|
||||
return loadByEmoteId(emote.getIdLong(), emote.getGuild().getIdLong());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean trackedEmoteExists(Long emoteId, Long serverId) {
|
||||
return loadByEmoteIdOptional(emoteId, serverId).isPresent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TrackedEmote loadByTrackedEmoteServer(TrackedEmoteServer trackedEmoteServer) {
|
||||
return loadByEmoteId(trackedEmoteServer.getEmoteId(), trackedEmoteServer.getServerId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<TrackedEmote> loadByEmoteIdOptional(Long emoteId, Long serverId) {
|
||||
return repository.findById(new TrackedEmoteServer(emoteId, serverId));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TrackedEmote> getAllActiveTrackedEmoteForServer(AServer server) {
|
||||
return getAllActiveTrackedEmoteForServer(server.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TrackedEmote> getAllActiveTrackedEmoteForServer(Long serverId) {
|
||||
return repository.findByTrackedEmoteId_ServerIdAndDeletedFalseAndExternalFalse(serverId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TrackedEmote> getTrackedEmoteForServer(Long serverId, Boolean showTrackingDisabledEmotes) {
|
||||
if(showTrackingDisabledEmotes) {
|
||||
return repository.findByTrackedEmoteId_ServerId(serverId);
|
||||
} else {
|
||||
return repository.findByTrackedEmoteId_ServerIdAndTrackingEnabledTrue(serverId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void changeName(TrackedEmote emote, String newName) {
|
||||
log.info("Changing name of emote {} in server {}.", emote.getTrackedEmoteId().getEmoteId(), emote.getTrackedEmoteId().getServerId());
|
||||
emote.setEmoteName(newName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disableTrackedEmote(TrackedEmote emote) {
|
||||
log.info("Disabling tracking for tracked emote {} in server {}.", emote.getTrackedEmoteId().getEmoteId(), emote.getTrackedEmoteId().getServerId());
|
||||
emote.setTrackingEnabled(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enableTrackedEmote(TrackedEmote emote) {
|
||||
log.info("Enabling tracking for tracked emote {} in server {}.", emote.getTrackedEmoteId().getEmoteId(), emote.getTrackedEmoteId().getServerId());
|
||||
emote.setTrackingEnabled(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteTrackedEmote(TrackedEmote emote) {
|
||||
log.info("Deleting tracked emote {} in server {}.", emote.getTrackedEmoteId().getEmoteId(), emote.getTrackedEmoteId().getServerId());
|
||||
repository.delete(emote);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
package dev.sheldan.abstracto.statistic.emotes.service.management;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import dev.sheldan.abstracto.statistic.emotes.model.EmoteStatsResult;
|
||||
import dev.sheldan.abstracto.statistic.emotes.model.database.TrackedEmote;
|
||||
import dev.sheldan.abstracto.statistic.emotes.model.database.UsedEmote;
|
||||
import dev.sheldan.abstracto.statistic.emotes.model.database.embed.UsedEmoteDay;
|
||||
import dev.sheldan.abstracto.statistic.emotes.repository.UsedEmoteRepository;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class UsedEmoteManagementServiceBean implements UsedEmoteManagementService {
|
||||
|
||||
@Autowired
|
||||
private UsedEmoteRepository usedEmoteRepository;
|
||||
|
||||
@Override
|
||||
public Optional<UsedEmote> loadUsedEmoteForTrackedEmoteToday(TrackedEmote trackedEmote) {
|
||||
return usedEmoteRepository.findEmoteFromServerToday(trackedEmote.getTrackedEmoteId().getEmoteId() , trackedEmote.getTrackedEmoteId().getServerId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public UsedEmote createEmoteUsageForToday(TrackedEmote trackedEmote, Long count) {
|
||||
UsedEmote usedEmote = UsedEmote
|
||||
.builder()
|
||||
.emoteId(new UsedEmoteDay(trackedEmote.getTrackedEmoteId().getEmoteId(), trackedEmote.getTrackedEmoteId().getServerId(), Instant.now()))
|
||||
.amount(count)
|
||||
.build();
|
||||
log.trace("Creating emote usage for emote {} in server {} with count {}.", trackedEmote.getTrackedEmoteId().getEmoteId(), trackedEmote.getTrackedEmoteId().getServerId(), count);
|
||||
return usedEmoteRepository.save(usedEmote);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UsedEmote> loadEmoteUsagesForServerSince(AServer server, Instant since) {
|
||||
return usedEmoteRepository.getByEmoteId_ServerIdAndEmoteId_UseDateGreaterThan(server.getId(), since);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<EmoteStatsResult> loadAllEmoteStatsForServerSince(AServer server, Instant since) {
|
||||
return usedEmoteRepository.getEmoteStatsForServerSince(server.getId(), since);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<EmoteStatsResult> loadDeletedEmoteStatsForServerSince(AServer server, Instant since) {
|
||||
return usedEmoteRepository.getDeletedEmoteStatsForServerSince(server.getId(), since);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<EmoteStatsResult> loadExternalEmoteStatsForServerSince(AServer server, Instant since) {
|
||||
return usedEmoteRepository.getExternalEmoteStatsForServerSince(server.getId(), since);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<EmoteStatsResult> loadActiveEmoteStatsForServerSince(AServer server, Instant since) {
|
||||
return usedEmoteRepository.getCurrentlyExistingEmoteStatsForServerSince(server.getId(), since);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void purgeEmoteUsagesSince(TrackedEmote emote, Instant since) {
|
||||
usedEmoteRepository.deleteByEmoteId_EmoteIdAndEmoteId_ServerIdAndEmoteId_UseDateGreaterThan(emote.getTrackedEmoteId().getEmoteId(), emote.getTrackedEmoteId().getServerId(), since);
|
||||
}
|
||||
}
|
||||
@@ -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-3.8.xsd
|
||||
http://www.liquibase.org/xml/ns/dbchangelog-ext ../dbchangelog-3.8.xsd
|
||||
http://www.liquibase.org/xml/ns/pro ../dbchangelog-3.8.xsd" >
|
||||
<include file="statistic-tables/tables.xml" relativeToChangelogFile="true"/>
|
||||
<include file="statistic-seedData/data.xml" relativeToChangelogFile="true"/>
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,88 @@
|
||||
<?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-3.8.xsd
|
||||
http://www.liquibase.org/xml/ns/dbchangelog-ext ../../dbchangelog-3.8.xsd
|
||||
http://www.liquibase.org/xml/ns/pro ../../dbchangelog-3.8.xsd" >
|
||||
<property name="statisticModule" value="(SELECT id FROM module WHERE name = 'statistic')"/>
|
||||
<property name="emoteTrackingFeature" value="(SELECT id FROM feature WHERE key = 'emote_tracking')"/>
|
||||
<property name="today" value="(SELECT NOW())"/>
|
||||
|
||||
<changeSet author="Sheldan" id="statistic-commands">
|
||||
<insert tableName="command">
|
||||
<column name="name" value="emoteStats"/>
|
||||
<column name="module_id" valueComputed="${statisticModule}"/>
|
||||
<column name="feature_id" valueComputed="${emoteTrackingFeature}"/>
|
||||
<column name="created" valueComputed="${today}"/>
|
||||
</insert>
|
||||
<insert tableName="command">
|
||||
<column name="name" value="deletedEmoteStats"/>
|
||||
<column name="module_id" valueComputed="${statisticModule}"/>
|
||||
<column name="feature_id" valueComputed="${emoteTrackingFeature}"/>
|
||||
<column name="created" valueComputed="${today}"/>
|
||||
</insert>
|
||||
<insert tableName="command">
|
||||
<column name="name" value="externalEmoteStats"/>
|
||||
<column name="module_id" valueComputed="${statisticModule}"/>
|
||||
<column name="feature_id" valueComputed="${emoteTrackingFeature}"/>
|
||||
<column name="created" valueComputed="${today}"/>
|
||||
</insert>
|
||||
<insert tableName="command">
|
||||
<column name="name" value="purgeEmoteStats"/>
|
||||
<column name="module_id" valueComputed="${statisticModule}"/>
|
||||
<column name="feature_id" valueComputed="${emoteTrackingFeature}"/>
|
||||
<column name="created" valueComputed="${today}"/>
|
||||
</insert>
|
||||
<insert tableName="command">
|
||||
<column name="name" value="syncTrackedEmotes"/>
|
||||
<column name="module_id" valueComputed="${statisticModule}"/>
|
||||
<column name="feature_id" valueComputed="${emoteTrackingFeature}"/>
|
||||
<column name="created" valueComputed="${today}"/>
|
||||
</insert>
|
||||
<insert tableName="command">
|
||||
<column name="name" value="trackEmote"/>
|
||||
<column name="module_id" valueComputed="${statisticModule}"/>
|
||||
<column name="feature_id" valueComputed="${emoteTrackingFeature}"/>
|
||||
<column name="created" valueComputed="${today}"/>
|
||||
</insert>
|
||||
<insert tableName="command">
|
||||
<column name="name" value="disableEmoteTracking"/>
|
||||
<column name="module_id" valueComputed="${statisticModule}"/>
|
||||
<column name="feature_id" valueComputed="${emoteTrackingFeature}"/>
|
||||
<column name="created" valueComputed="${today}"/>
|
||||
</insert>
|
||||
<insert tableName="command">
|
||||
<column name="name" value="deleteTrackedEmote"/>
|
||||
<column name="module_id" valueComputed="${statisticModule}"/>
|
||||
<column name="feature_id" valueComputed="${emoteTrackingFeature}"/>
|
||||
<column name="created" valueComputed="${today}"/>
|
||||
</insert>
|
||||
<insert tableName="command">
|
||||
<column name="name" value="resetEmoteStats"/>
|
||||
<column name="module_id" valueComputed="${statisticModule}"/>
|
||||
<column name="feature_id" valueComputed="${emoteTrackingFeature}"/>
|
||||
<column name="created" valueComputed="${today}"/>
|
||||
</insert>
|
||||
<insert tableName="command">
|
||||
<column name="name" value="exportEmoteStats"/>
|
||||
<column name="module_id" valueComputed="${statisticModule}"/>
|
||||
<column name="feature_id" valueComputed="${emoteTrackingFeature}"/>
|
||||
<column name="created" valueComputed="${today}"/>
|
||||
</insert>
|
||||
<insert tableName="command">
|
||||
<column name="name" value="showExternalTrackedEmote"/>
|
||||
<column name="module_id" valueComputed="${statisticModule}"/>
|
||||
<column name="feature_id" valueComputed="${emoteTrackingFeature}"/>
|
||||
<column name="created" valueComputed="${today}"/>
|
||||
</insert>
|
||||
<insert tableName="command">
|
||||
<column name="name" value="showTrackedEmotes"/>
|
||||
<column name="module_id" valueComputed="${statisticModule}"/>
|
||||
<column name="feature_id" valueComputed="${emoteTrackingFeature}"/>
|
||||
<column name="created" valueComputed="${today}"/>
|
||||
</insert>
|
||||
</changeSet>
|
||||
|
||||
</databaseChangeLog>
|
||||
@@ -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-3.8.xsd
|
||||
http://www.liquibase.org/xml/ns/dbchangelog-ext ../../dbchangelog-3.8.xsd
|
||||
http://www.liquibase.org/xml/ns/pro ../../dbchangelog-3.8.xsd" >
|
||||
<include file="feature.xml" relativeToChangelogFile="true"/>
|
||||
<include file="module.xml" relativeToChangelogFile="true"/>
|
||||
<include file="default_feature_flag.xml" relativeToChangelogFile="true"/>
|
||||
<include file="emote_statistic_job.xml" relativeToChangelogFile="true"/>
|
||||
<include file="command.xml" relativeToChangelogFile="true"/>
|
||||
<include file="default_feature_mode.xml" relativeToChangelogFile="true"/>
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,18 @@
|
||||
<?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-3.8.xsd
|
||||
http://www.liquibase.org/xml/ns/dbchangelog-ext ../../dbchangelog-3.8.xsd
|
||||
http://www.liquibase.org/xml/ns/pro ../../dbchangelog-3.8.xsd" >
|
||||
<property name="emoteTrackingFeature" value="(SELECT id FROM feature WHERE key = 'emote_tracking')"/>
|
||||
<property name="today" value="(SELECT NOW())"/>
|
||||
<changeSet author="Sheldan" id="emote_tracking_default_feature_flag-insertion">
|
||||
<insert tableName="default_feature_flag">
|
||||
<column name="enabled" value="false"/>
|
||||
<column name="feature_id" valueComputed="${emoteTrackingFeature}" />
|
||||
<column name="created" valueComputed="${today}"/>
|
||||
</insert>
|
||||
</changeSet>
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,31 @@
|
||||
<?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-3.8.xsd
|
||||
http://www.liquibase.org/xml/ns/dbchangelog-ext ../../dbchangelog-3.8.xsd
|
||||
http://www.liquibase.org/xml/ns/pro ../../dbchangelog-3.8.xsd" >
|
||||
<property name="emoteTrackingFeature" value="(SELECT id FROM feature WHERE key = 'emote_tracking')"/>
|
||||
<property name="today" value="(SELECT NOW())"/>
|
||||
<changeSet author="Sheldan" id="emote_tracking_default_feature_mode-insertion">
|
||||
<insert tableName="default_feature_mode">
|
||||
<column name="enabled" value="true"/>
|
||||
<column name="mode" value="emoteAutoTrack"/>
|
||||
<column name="feature_id" valueComputed="${emoteTrackingFeature}" />
|
||||
<column name="created" valueComputed="${today}"/>
|
||||
</insert>
|
||||
<insert tableName="default_feature_mode">
|
||||
<column name="enabled" value="false"/>
|
||||
<column name="mode" value="externalEmotes"/>
|
||||
<column name="feature_id" valueComputed="${emoteTrackingFeature}" />
|
||||
<column name="created" valueComputed="${today}"/>
|
||||
</insert>
|
||||
<insert tableName="default_feature_mode">
|
||||
<column name="enabled" value="false"/>
|
||||
<column name="mode" value="autoTrackExternal"/>
|
||||
<column name="feature_id" valueComputed="${emoteTrackingFeature}" />
|
||||
<column name="created" valueComputed="${today}"/>
|
||||
</insert>
|
||||
</changeSet>
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,19 @@
|
||||
<?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-3.8.xsd
|
||||
http://www.liquibase.org/xml/ns/dbchangelog-ext ../../dbchangelog-3.8.xsd
|
||||
http://www.liquibase.org/xml/ns/pro ../../dbchangelog-3.8.xsd" >
|
||||
<changeSet author="Sheldan" id="emote-statistic-job-insert">
|
||||
<insert tableName="scheduler_job">
|
||||
<column name="name" value="emoteStatisticJob"/>
|
||||
<column name="group_name" value="statistic"/>
|
||||
<column name="clazz" value="dev.sheldan.abstracto.statistic.emotes.job.EmotePersistingJob"/>
|
||||
<column name="active" value="true"/>
|
||||
<column name="cron_expression" value="40 * * * * ?"/>
|
||||
<column name="recovery" value="false"/>
|
||||
</insert>
|
||||
</changeSet>
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,16 @@
|
||||
<?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-3.8.xsd
|
||||
http://www.liquibase.org/xml/ns/dbchangelog-ext ../../dbchangelog-3.8.xsd
|
||||
http://www.liquibase.org/xml/ns/pro ../../dbchangelog-3.8.xsd" >
|
||||
<property name="today" value="(SELECT NOW())"/>
|
||||
<changeSet author="Sheldan" id="emote_tracking_feature-insertion">
|
||||
<insert tableName="feature">
|
||||
<column name="key" value="emote_tracking"/>
|
||||
<column name="created" valueComputed="${today}"/>
|
||||
</insert>
|
||||
</changeSet>
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,16 @@
|
||||
<?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-3.8.xsd
|
||||
http://www.liquibase.org/xml/ns/dbchangelog-ext ../../dbchangelog-3.8.xsd
|
||||
http://www.liquibase.org/xml/ns/pro ../../dbchangelog-3.8.xsd" >
|
||||
<property name="today" value="(SELECT NOW())"/>
|
||||
<changeSet author="Sheldan" id="statistic-module-insertion">
|
||||
<insert tableName="module">
|
||||
<column name="name" value="statistic"/>
|
||||
<column name="created" valueComputed="${today}"/>
|
||||
</insert>
|
||||
</changeSet>
|
||||
</databaseChangeLog>
|
||||
@@ -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-3.8.xsd
|
||||
http://www.liquibase.org/xml/ns/dbchangelog-ext ../../dbchangelog-3.8.xsd
|
||||
http://www.liquibase.org/xml/ns/pro ../../dbchangelog-3.8.xsd" >
|
||||
<include file="tracked_emote.xml" relativeToChangelogFile="true"/>
|
||||
<include file="used_emote.xml" relativeToChangelogFile="true"/>
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,30 @@
|
||||
<?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-3.8.xsd
|
||||
http://www.liquibase.org/xml/ns/dbchangelog-ext ../../dbchangelog-3.8.xsd
|
||||
http://www.liquibase.org/xml/ns/pro ../../dbchangelog-3.8.xsd" >
|
||||
<changeSet author="Sheldan" id="tracked_emote-table">
|
||||
<createTable tableName="tracked_emote">
|
||||
<column name="id" type="BIGINT">
|
||||
<constraints nullable="false" primaryKey="true" primaryKeyName="tracked_emote_pkey"/>
|
||||
</column>
|
||||
<column name="updated" type="TIMESTAMP WITHOUT TIME ZONE"/>
|
||||
<column name="created" type="TIMESTAMP WITHOUT TIME ZONE"/>
|
||||
<column name="name" type="VARCHAR(32)"/>
|
||||
<column name="animated" type="BOOLEAN"/>
|
||||
<column name="tracking_enabled" type="BOOLEAN"/>
|
||||
<column name="deleted" type="BOOLEAN"/>
|
||||
<column name="external" type="BOOLEAN"/>
|
||||
<column name="external_url" type="VARCHAR(255)"/>
|
||||
<column name="server_id" type="BIGINT">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
</createTable>
|
||||
</changeSet>
|
||||
<changeSet author="Sheldan" id="tracked_emote-fk_tracked_emote_server">
|
||||
<addForeignKeyConstraint baseColumnNames="server_id" baseTableName="tracked_emote" constraintName="fk_tracked_emote_server" deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION" referencedColumnNames="id" referencedTableName="server" validate="true"/>
|
||||
</changeSet>
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,29 @@
|
||||
<?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-3.8.xsd
|
||||
http://www.liquibase.org/xml/ns/dbchangelog-ext ../../dbchangelog-3.8.xsd
|
||||
http://www.liquibase.org/xml/ns/pro ../../dbchangelog-3.8.xsd" >
|
||||
<changeSet author="Sheldan" id="used_emote-table">
|
||||
<createTable tableName="used_emote">
|
||||
<column name="emote_id" type="BIGINT">
|
||||
<constraints nullable="false" primaryKey="true" primaryKeyName="used_emote_pkey"/>
|
||||
</column>
|
||||
<column name="server_id" type="BIGINT">
|
||||
<constraints nullable="false" primaryKey="true" primaryKeyName="used_emote_pkey"/>
|
||||
</column>
|
||||
<column name="use_date" type="DATE">
|
||||
<constraints nullable="false" primaryKey="true" primaryKeyName="used_emote_pkey"/>
|
||||
</column>
|
||||
<column name="amount" type="BIGINT"/>
|
||||
</createTable>
|
||||
</changeSet>
|
||||
<changeSet author="Sheldan" id="used_emote-fk_used_emote_server">
|
||||
<addForeignKeyConstraint baseColumnNames="server_id" baseTableName="used_emote" constraintName="fk_used_emote_server" deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION" referencedColumnNames="id" referencedTableName="server" validate="true"/>
|
||||
</changeSet>
|
||||
<changeSet author="Sheldan" id="used_emote-fk_used_emote_tracked_emote">
|
||||
<addForeignKeyConstraint baseColumnNames="emote_id" baseTableName="used_emote" constraintName="fk_used_emote_tracked_emote" deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION" referencedColumnNames="id" referencedTableName="tracked_emote" validate="true"/>
|
||||
</changeSet>
|
||||
</databaseChangeLog>
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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-3.8.xsd
|
||||
http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog-3.8.xsd
|
||||
http://www.liquibase.org/xml/ns/pro dbchangelog-3.8.xsd" >
|
||||
<include file="1.0-statistic/collection.xml" relativeToChangelogFile="true"/>
|
||||
</databaseChangeLog>
|
||||
Reference in New Issue
Block a user