[AB-60] added java doc for statistic module, added feature mode limitations to emote listener, replaced redundant Embeddable with ServerSpecificId

This commit is contained in:
Sheldan
2020-11-23 02:27:49 +01:00
parent b05a834b59
commit e966c710ce
68 changed files with 1219 additions and 218 deletions

View File

@@ -2,10 +2,16 @@ package dev.sheldan.abstracto.statistic.config;
import dev.sheldan.abstracto.core.config.FeatureEnum;
/**
* Features available in the statistic module.
*/
public enum StatisticFeatures implements FeatureEnum {
/**
* Feature responsible to track the emotes used in a message on a server.
*/
EMOTE_TRACKING("emote_tracking");
private String key;
private final String key;
StatisticFeatures(String key) {
this.key = key;

View File

@@ -9,13 +9,24 @@ import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.List;
/**
* {@link FeatureConfig} implementation to define the EmoteTracking feature.
*/
@Component
public class EmoteTrackingFeature implements FeatureConfig {
/**
* {@link FeatureEnum} represents the feature uniquely
*/
@Override
public FeatureEnum getFeature() {
return StatisticFeatures.EMOTE_TRACKING;
}
/**
* This feature contains three feature modes. For explanation of them check {@link EmoteTrackingFeature}
* @return list of {@link FeatureMode} handled by this feature.
*/
@Override
public List<FeatureMode> getAvailableModes() {
return Arrays.asList(EmoteTrackingMode.EXTERNAL_EMOTES, EmoteTrackingMode.AUTO_TRACK, EmoteTrackingMode.AUTO_TRACK_EXTERNAL);

View File

@@ -3,6 +3,13 @@ package dev.sheldan.abstracto.statistic.emotes.config;
import dev.sheldan.abstracto.core.config.FeatureMode;
import lombok.Getter;
/**
* {@link FeatureMode}s for {@link EmoteTrackingFeature}. These modes include:
* AUTO_TRACK: This controls a listener which listens for the emote events of a server, and automatically creates/updates/marks as deleted instances in the database if the respective event happens
* Influences:
* EXTERNAL_EMOTES: Enables the tracking of emotes which are not from the server the feature is enabled in. This feature alone only enables to track emotes with the `trackEmote` command and makes the command `externalEmoteStats` (and more) available
* AUTO_TRACK_EXTERNAL: Every external emote which is encountered in a message will be tracked (created and updated), only works in combination with EXTERNAL_MOTES
*/
@Getter
public enum EmoteTrackingMode implements FeatureMode {
AUTO_TRACK("emoteAutoTrack"), EXTERNAL_EMOTES("externalEmotes"), AUTO_TRACK_EXTERNAL("autoTrackExternal");

View File

@@ -4,6 +4,10 @@ import dev.sheldan.abstracto.core.exception.AbstractoRunTimeException;
import dev.sheldan.abstracto.statistic.emotes.model.exception.DownloadEmoteStatsFileTooBigModel;
import dev.sheldan.abstracto.templating.Templatable;
/**
* Exception in case the CSV file created by `exportEmoteStats` is larger than the file size limit of the guild it was requested in.
* TODO: split this up into multiple files (total max), in order to make this exception obsolete
*/
public class DownloadEmoteStatsFileTooBigException extends AbstractoRunTimeException implements Templatable {
private final DownloadEmoteStatsFileTooBigModel model;

View File

@@ -1,8 +1,13 @@
package dev.sheldan.abstracto.statistic.emotes.exception;
import dev.sheldan.abstracto.core.exception.AbstractoRunTimeException;
import dev.sheldan.abstracto.templating.Templatable;
public class TrackedEmoteNotFoundException extends AbstractoRunTimeException {
/**
* Exception which is cased in a case the {@link dev.sheldan.abstracto.statistic.emotes.model.database.TrackedEmote} could not be found.
* The cases for this are currently wrapped with exist checks, but it will be raised if you call the method directly.
*/
public class TrackedEmoteNotFoundException extends AbstractoRunTimeException implements Templatable {
public TrackedEmoteNotFoundException(String message) {
super(message);
@@ -10,4 +15,14 @@ public class TrackedEmoteNotFoundException extends AbstractoRunTimeException {
public TrackedEmoteNotFoundException() {
}
@Override
public String getTemplateName() {
return "emote_stats_tracked_emote_not_found";
}
@Override
public Object getTemplateModel() {
return new Object();
}
}

View File

@@ -6,10 +6,20 @@ import lombok.Getter;
import lombok.Setter;
import net.dv8tion.jda.api.entities.Emote;
/**
* Model which is used to render in emotes for the command `showTrackedEmotes`, which still exist in the server.
* This means there is a {@link Emote} instance available.
*/
@Getter
@Setter
@Builder
public class AvailableTrackedEmote {
/**
* The {@link Emote} instance of the {@link TrackedEmote} to show
*/
private Emote emote;
/**
* The original {@link TrackedEmote} instance from the server to show
*/
private TrackedEmote trackedEmote;
}

View File

@@ -0,0 +1,40 @@
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;
/**
* Model used to render the file produced by `exportEmoteStats`
*/
@Getter
@Setter
@Builder
public class DownloadEmoteStatsModel {
/**
* The {@link Guild} for which the emote stats are being exportet
*/
private Guild guild;
/**
* The date this export has been performed on
*/
private Instant downloadDate;
/**
* The {@link Instant} which was used as the cut-off point in time to retrieve the emote stats for
*/
private Instant statsSince;
/**
* The {@link Member} who requested the export
*/
private Member requester;
/**
* A list of {@link UsedEmote} which are part of the export
*/
private List<UsedEmote> emotes;
}

View File

@@ -9,16 +9,32 @@ import net.dv8tion.jda.api.entities.Guild;
import java.util.ArrayList;
import java.util.List;
/**
* The model used to render a `*emoteStats` result. This is split up into animated and static emotes, and will only
* represent one type of these three: still existing, deleted and external. A guild instance is added for convenience.
*/
@Getter
@Setter
@Builder
public class EmoteStatsModel {
/**
* The list of {@link EmoteStatsResultDisplay} which represent the animated emotes from the result
*/
@Builder.Default
private List<EmoteStatsResultDisplay> animatedEmotes = new ArrayList<>();
/**
* The list of {@link EmoteStatsResultDisplay} which represent the static emotes from the result
*/
@Builder.Default
private List<EmoteStatsResultDisplay> staticEmotes = new ArrayList<>();
/**
* The server the emote stats have been retrieved for.
*/
private Guild guild;
/**
* Whether or not this model contains *any* stats to render.
*/
public boolean areStatsAvailable() {
return !animatedEmotes.isEmpty() || !staticEmotes.isEmpty();
}

View File

@@ -1,7 +1,22 @@
package dev.sheldan.abstracto.statistic.emotes.model;
/**
* The interface used to fill with values from the emote stats query. This represents the grouped result consisting of:
* the ID of the emote, the ID of the server and the amount of times this emote has been used in the server
*/
public interface EmoteStatsResult {
/**
* ID of the emote
*/
Long getEmoteId();
/**
* ID of the server
*/
Long getServerId();
/**
* Amount the emote with the ID has been used in the server with the ID
*/
Long getAmount();
}

View File

@@ -6,11 +6,25 @@ import lombok.Getter;
import lombok.Setter;
import net.dv8tion.jda.api.entities.Emote;
/**
* Model used to render the emote stats for various commands. This contains the concrete {@link Emote} (if available).
* This is only the case for emotes from the server. For external and deleted emotes, only {@link EmoteStatsResultDisplay} and
* {@link TrackedEmote} will be available.
*/
@Getter
@Setter
@Builder
public class EmoteStatsResultDisplay {
/**
* The actual {@link Emote} from the server, if available. Not available for deleted and external emotes.
*/
private Emote emote;
/**
* The {@link EmoteStatsResult} for one particular emote, containing the amount of times the emote has been used.
*/
private EmoteStatsResult result;
/**
* An instance of {@link TrackedEmote} for which this result has been retrieved.
*/
private TrackedEmote trackedEmote;
}

View File

@@ -4,15 +4,41 @@ import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
/**
* This model is used to store the usages of an {@link dev.sheldan.abstracto.statistic.emotes.model.database.TrackedEmote} in runtime.
* It does not store JDA related entities, but rather direct values.
*/
@Getter
@Setter
@Builder
public class PersistingEmote {
/**
* The global unique ID of the {@link net.dv8tion.jda.api.entities.Emote}
*/
private Long emoteId;
/**
* The name of the {@link net.dv8tion.jda.api.entities.Emote} in Discord
*/
private String emoteName;
/**
* Whether or not the {@link net.dv8tion.jda.api.entities.Emote} is animated
*/
private Boolean animated;
/**
* Whether or not the emote is from the {@link net.dv8tion.jda.api.entities.Guild} the {@link net.dv8tion.jda.api.entities.Message}
* has been received on
*/
private Boolean external;
/**
* Only if the emote is external: the URL where the source image of the {@link net.dv8tion.jda.api.entities.Emote} is stored on Discord servers
*/
private String externalUrl;
/**
* The amount of times the {@link net.dv8tion.jda.api.entities.Emote} has been used.
*/
private Long count;
/**
* The ID of the {@link net.dv8tion.jda.api.entities.Guild} on which the {@link net.dv8tion.jda.api.entities.Emote} has been used on
*/
private Long serverId;
}

View File

@@ -9,30 +9,61 @@ import net.dv8tion.jda.api.entities.Guild;
import java.util.ArrayList;
import java.util.List;
/**
* Model used to render the currently tracked emotes of a {@link Guild}. They are split up into
* the static/animated emotes from the server itself. The {@link net.dv8tion.jda.internal.requests.Route.Emotes}
* which were previously on the server and (if enabled) all external {@link TrackedEmote} from the server.
*/
@Getter
@Setter
@Builder
public class TrackedEmoteOverview {
/**
* A list of {@link AvailableTrackedEmote} containing the static emotes of the {@link Guild} this command has been executed for.
*/
@Builder.Default
private List<AvailableTrackedEmote> animatedEmotes = new ArrayList<>();
/**
* A list of {@link AvailableTrackedEmote} containing the animated emotes of the {@link Guild} this command has been executed for.
*/
@Builder.Default
private List<AvailableTrackedEmote> staticEmotes = new ArrayList<>();
/**
* A list of {@link TrackedEmote} containing the static emotes which were previously in the {@link Guild}, but have since been deleted
*/
@Builder.Default
private List<TrackedEmote> deletedStaticEmotes = new ArrayList<>();
/**
* A list of {@link TrackedEmote} containing the animated emotes which were previously in the {@link Guild}, but have since been deleted
*/
@Builder.Default
private List<TrackedEmote> deletedAnimatedEmotes = new ArrayList<>();
/**
* A list of {@link TrackedEmote} containing the static emotes which were used on the {@link Guild}, but are not from that {@link Guild}.
*/
@Builder.Default
private List<TrackedEmote> externalStaticEmotes = new ArrayList<>();
/**
* A list of {@link TrackedEmote} containing the animated emotes which were used on the {@link Guild}, but are not from that {@link Guild}.
*/
@Builder.Default
private List<TrackedEmote> externalAnimatedEmotes = new ArrayList<>();
/**
* The {@link Guild} for which the {@link TrackedEmote}s have been retrieved.
*/
private Guild guild;
/**
* Adds the {@link TrackedEmote} to the correct list in this model, depending on the properties of the tracked emote.
* @param trackedEmote The {@link TrackedEmote} instance to add to the lists
* @param guild The {@link Guild} in which trackedEmote is being tracked
*/
public void addTrackedEmote(TrackedEmote trackedEmote, Guild guild) {
if(trackedEmote.getDeleted()) {
if(trackedEmote.getAnimated()) {
@@ -49,7 +80,7 @@ public class TrackedEmoteOverview {
} else {
AvailableTrackedEmote availableEmote = AvailableTrackedEmote
.builder()
.emote(guild.getEmoteById(trackedEmote.getTrackedEmoteId().getEmoteId()))
.emote(guild.getEmoteById(trackedEmote.getTrackedEmoteId().getId()))
.trackedEmote(trackedEmote)
.build();
if(trackedEmote.getAnimated()) {

View File

@@ -4,10 +4,21 @@ import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
/**
* Model containing the result of `syncTrackedEmotes`. The two numbers are the amount of {@link dev.sheldan.abstracto.statistic.emotes.model.database.TrackedEmote}
* which were created and marked as deleted.
*
*/
@Getter
@Setter
@Builder
public class TrackedEmoteSynchronizationResult {
/**
* The amount of {@link dev.sheldan.abstracto.statistic.emotes.model.database.TrackedEmote} which were created because of the synchronization
*/
private Long emotesAdded;
/**
* The amount of {@link dev.sheldan.abstracto.statistic.emotes.model.database.TrackedEmote} which were marked as deleted because of the synchronization
*/
private Long emotesMarkedDeleted;
}

View File

@@ -1,8 +1,8 @@
package dev.sheldan.abstracto.statistic.emotes.model.database;
import dev.sheldan.abstracto.core.models.Fakeable;
import dev.sheldan.abstracto.core.models.ServerSpecificId;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.statistic.emotes.model.database.embed.TrackedEmoteServer;
import lombok.*;
import org.hibernate.annotations.CacheConcurrencyStrategy;
@@ -10,6 +10,11 @@ import javax.persistence.*;
import java.io.Serializable;
import java.time.Instant;
/**
* The instance of an emote which is being tracked by {@link dev.sheldan.abstracto.statistic.emotes.config.EmoteTrackingFeature}.
* This represents an emote by its unique ID and the respective server its being tracked in. This emote might not be part of the server
* and might have been deleted.
*/
@Builder
@Entity
@NoArgsConstructor
@@ -23,28 +28,50 @@ import java.time.Instant;
public class TrackedEmote implements Serializable, Fakeable {
@EmbeddedId
private TrackedEmoteServer trackedEmoteId;
private ServerSpecificId trackedEmoteId;
@ManyToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE})
@MapsId("serverId")
@JoinColumn(name = "server_id", referencedColumnName = "id", nullable = false)
private AServer server;
/**
* The name of the {@link net.dv8tion.jda.api.entities.Emote} which is the same how it is identified within Discord.
*/
@Column(name = "name", length = 32)
private String emoteName;
/**
* Whether or not the emote is animated.
*/
@Column(name = "animated")
private Boolean animated;
/**
* Whether or not the tracking for this emote is enabled. Tracking enabled means, that the listener counts the usages of this emote
* in the *Messages*.
*/
@Column(name = "tracking_enabled")
private Boolean trackingEnabled;
/**
* Whether or not the emote has been deleted from the server. This is only relevant for emotes which originated from the server
* the feature is being used in. This does not have any meaning for external emotes.
*/
@Column(name = "deleted")
private Boolean deleted;
/**
* Whether or not the emote was *not* from the server the feature is being used in. This means, that the emote is from a foreign server
* and we cannot identify the true server this emote is from.
*/
@Column(name = "external")
private Boolean external;
/**
* The URL of the picture which is associated with the emote. This is only used for external emotes and only actively used when
* a user wants to see the picture of the emote with the command `showExternalTrackedEmote`
*/
@Column(name = "external_url")
private String externalUrl;
@@ -64,6 +91,12 @@ public class TrackedEmote implements Serializable, Fakeable {
this.updated = Instant.now();
}
/**
* Some emotes are build on demand, and do not necessarily be persisted. This happens when the emote is being used as a
* {@link dev.sheldan.abstracto.core.command.config.Parameter}.
* If a command uses this as a parameter, it is advised to actually load the {@link TrackedEmote} before using it, because it
* is not guaranteed that it actually exists.
*/
@Transient
private boolean fake;
}

View File

@@ -6,6 +6,9 @@ import org.hibernate.annotations.CacheConcurrencyStrategy;
import javax.persistence.*;
/**
* An actual instance which has been used on a certain date with a certain amount.
*/
@Builder
@Entity
@NoArgsConstructor
@@ -18,9 +21,15 @@ import javax.persistence.*;
@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class UsedEmote {
/**
* The unique identifier for the emote: the ID of the emote, the ID of the server it was used in, the *date* the emote was used on.
*/
@EmbeddedId
private UsedEmoteDay emoteId;
/**
* Reference to the {@link TrackedEmote} which was used at the given date
*/
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumns(
{
@@ -29,6 +38,9 @@ public class UsedEmote {
})
private TrackedEmote trackedEmote;
/**
* The amount this {@link TrackedEmote} has been used on this date
*/
@Column(name = "amount")
private Long amount;
}

View File

@@ -1,21 +0,0 @@
package dev.sheldan.abstracto.statistic.emotes.model.database.embed;
import lombok.*;
import javax.persistence.Column;
import javax.persistence.Embeddable;
import java.io.Serializable;
@Embeddable
@Getter
@Setter
@EqualsAndHashCode
@AllArgsConstructor
@NoArgsConstructor
public class TrackedEmoteServer implements Serializable {
@Column(name = "id")
private Long emoteId;
@Column(name = "server_id")
private Long serverId;
}

View File

@@ -7,6 +7,10 @@ import javax.persistence.Embeddable;
import java.io.Serializable;
import java.time.Instant;
/**
* This {@link Embeddable} is used to create the composite primary key of {@link dev.sheldan.abstracto.statistic.emotes.model.database.UsedEmote}
* which consists of the `emote_id` (long), `server_id` (long) and the `use_date` (date)
*/
@Embeddable
@Getter
@Setter
@@ -15,11 +19,21 @@ import java.time.Instant;
@NoArgsConstructor
public class UsedEmoteDay implements Serializable {
/**
* The globally unique ID of the emote
*/
@Column(name = "emote_id")
private Long emoteId;
/**
* The ID of the {@link net.dv8tion.jda.api.entities.Guild} where this emote is *tracked* in. This does not mean, that the emote originated from this server,
* just that it is part of the tracked emotes of the server.
*/
@Column(name = "server_id")
private Long serverId;
/**
* The *day* the emote was used, this is represented as an {@link Instant} here, but in the actual database its only a date
*/
@Column(name = "use_date")
private Instant useDate;
}

View File

@@ -6,10 +6,20 @@ import lombok.Setter;
import java.io.Serializable;
/**
* Model used for {@link dev.sheldan.abstracto.statistic.emotes.exception.DownloadEmoteStatsFileTooBigException} which contains
* the file size of the file which was created and the max file size allowed on the server.
*/
@Getter
@Setter
@Builder
public class DownloadEmoteStatsFileTooBigModel implements Serializable {
/**
* File size in bytes of the file being created for emote stats
*/
private Long fileSize;
/**
* The file size limit of the server in bytes which was lower than the files size of the file
*/
private Long fileSizeLimit;
}

View File

@@ -7,13 +7,68 @@ import net.dv8tion.jda.api.entities.Guild;
import java.util.List;
import java.util.Map;
/**
* Service responsible for managing and containing the runtime storage for emote statistics
*/
public interface TrackedEmoteRuntimeService {
/**
* Returns the current runtime configuration. You should acquire the lock with `takeLock` before.
* @return The Map containing the current runtime emote stats
*/
Map<Long, Map<Long, List<PersistingEmote>>> getRuntimeConfig();
/**
* Adds the given {@link Emote} used in the {@link Guild} to the runtime storage.
* The necessary lock will be acquired by this method.
* @param emote The {@link Emote} to add to the runtime storage
* @param guild The {@link Guild} in which the {@link Emote} is used
* @param external Whether or not the emote is external
*/
void addEmoteForServer(Emote emote, Guild guild, boolean external);
/**
* Adds the given {@link Emote} used in the {@link Guild} to the runtime storage.
* The necessary lock will be acquired by this method.
* @param emote The {@link Emote} to add to the runtime storage
* @param guild The {@link Guild} in which the {@link Emote} is used
* @param count The amount of usages which should be added
* @param external Whether or not the emote is external
*/
void addEmoteForServer(Emote emote, Guild guild, Long count, boolean external);
/**
* Calculates the key used for the Map containing the emote statistics.
* @return The calculated key to be used in the Map
*/
Long getKey();
/**
* Creates a {@link PersistingEmote} from the given parameters.
* @param guild The {@link Guild} in which the {@link Emote} is used
* @param emote The {@link Emote} to create a {@link PersistingEmote} from
* @param external Whether or not the {@link Emote} is external
* @return A created {@link PersistingEmote} instance from the {@link Emote}
*/
PersistingEmote createFromEmote(Guild guild, Emote emote, boolean external);
/**
* Creates a {@link PersistingEmote} from the given parameters.
* @param guild The {@link Guild} in which the {@link Emote} is used
* @param emote The {@link Emote} to create a {@link PersistingEmote} from
* @param count The amount of usages the {@link Emote} has been used
* @param external Whether or not the {@link Emote} is external
* @return A created {@link PersistingEmote} instance from the {@link Emote}
*/
PersistingEmote createFromEmote(Guild guild, Emote emote, Long count, boolean external);
/**
* Acquires the lock which should be used when accessing the runtime storage
*/
void takeLock();
/**
* Releases the lock which should be used then accessing the runtime storage
*/
void releaseLock();
}

View File

@@ -10,18 +10,111 @@ import net.dv8tion.jda.api.entities.Guild;
import java.util.Map;
import java.util.List;
/**
* Service responsible to provide operations on {@link TrackedEmote}
*/
public interface TrackedEmoteService {
/**
* Adds the given list of {@link Emote}s to the runtime storage for the given {@link Guild}
* @param emotes The list of {@link Emote}s to add to the runtime storage
* @param guild The {@link Guild} in which the {@link Emote}s were used and where the usages should be added
*/
void addEmoteToRuntimeStorage(List<Emote> emotes, Guild guild);
/**
* Adds the given {@link Emote} with the given amount to the runtime storage for the given {@link Guild}
* @param emote The {@link Emote} to add to the runtime storage
* @param guild The {@link Guild} in which the {@link Emote} was used and in which the usage should be added
* @param count The amount of times which the {@link Emote} has been used and should be reflected in the runtime storage
*/
void addEmoteToRuntimeStorage(Emote emote, Guild guild, Long count);
/**
* Takes the given map of server_ids with the list of {@link PersistingEmote} and stores the objects in the database
* Non existing {@link TrackedEmote} for the server will be created. Depending on the feature mode external emotes will be created.
* @param usagesToStore The map of server_ids to a List of {@link PersistingEmote} which should be stored in the database
*/
void storeEmoteStatistics(Map<Long, List<PersistingEmote>> usagesToStore);
/**
* Creates a fake {@link TrackedEmote} from the given {@link Emote} and {@link Guild}. This {@link TrackedEmote}
* is not persisted and has the fake value set to true
* @param emote The {@link Emote} to be used for the fake {@link TrackedEmote}
* @param guild The {@link Guild} to be used for the fake {@link TrackedEmote}
* @return The fake {@link TrackedEmote} which was created
*/
TrackedEmote getFakeTrackedEmote(Emote emote, Guild guild);
TrackedEmote getFakeTrackedEmote(Long id, Guild guild);
/**
* Creates a fake {@link TrackedEmote} from the given emote ID and server ID. This {@link TrackedEmote}
* is not persisted and has the fake value set to true
* @param emoteId The ID of an {@link Emote}
* @param guild The ID of an {@link dev.sheldan.abstracto.core.models.database.AServer}
* @return The fake {@link TrackedEmote} which was created
*/
TrackedEmote getFakeTrackedEmote(Long emoteId, Guild guild);
/**
* Checks the currently existing {@link Emote}s in the {@link Guild} with the currently {@link TrackedEmote} and synchronizes
* the state. This means: unknown {@link Emote} are created as {@link TrackedEmote} and already existing {@link TrackedEmote}
* which are not found in the {@link Guild} are marked as deleted.
* @param guild The {@link Guild} to synchronize the {@link Emote} for
* @return The {@link TrackedEmoteSynchronizationResult} which contains information about what changed (number of deletions and additions)
*/
TrackedEmoteSynchronizationResult synchronizeTrackedEmotes(Guild guild);
/**
* Loads all the {@link TrackedEmote} for the given {@link Guild} for which tracking is enabled into a {@link TrackedEmoteOverview}
* @param guild The {@link Guild} to retrieve the {@link TrackedEmote} for
* @return The {@link TrackedEmoteOverview} containing the {@link TrackedEmote} which have tracking enabled
*/
TrackedEmoteOverview loadTrackedEmoteOverview(Guild guild);
/**
* Loads all the {@link TrackedEmote} for the given {@link Guild}. If showTrackingDisabled is true, it will also
* show {@link TrackedEmote} for which tracking has been disabled
* @param guild The {@link Guild} to retrieve the {@link TrackedEmoteOverview} for
* @param showTrackingDisabled Whether or not to include {@link TrackedEmote} for which tracking has been disabled
* @return The {@link TrackedEmoteOverview} containing the retrieved {@link TrackedEmote} depending on the criteria
*/
TrackedEmoteOverview loadTrackedEmoteOverview(Guild guild, Boolean showTrackingDisabled);
TrackedEmote createFakeTrackedEmote(Emote emote, Guild guild);
TrackedEmote createFakeTrackedEmote(Emote emote, Guild guild, boolean external);
/**
* Creates a {@link TrackedEmote} from the {@link Emote} based on a usage in {@link Guild}
* This method detects if the {@link Emote} is external or not on its own.
* @param emote The {@link Emote} to create a {@link TrackedEmote} for
* @param guild The {@link Guild} for which the {@link TrackedEmote} should be created for
* @return The created {@link TrackedEmote} instance in the database
*/
TrackedEmote createTrackedEmote(Emote emote, Guild guild);
/**
* Creates a {@link TrackedEmote} from the {@link Emote} based on a usage in {@link Guild}
* @param emote The {@link Emote} to create a {@link TrackedEmote} for
* @param guild The {@link Guild} in which the {@link TrackedEmote} should be created for
* @param external Whether or not the {@link Emote} is part of the {@link Guild} or not
* @return The created {@link TrackedEmote} instance in the database
*/
TrackedEmote createTrackedEmote(Emote emote, Guild guild, boolean external);
/**
* Deletes the referenced {@link TrackedEmote} in the database
* @param trackedEmote The {@link TrackedEmote} to delete
*/
void deleteTrackedEmote(TrackedEmote trackedEmote);
/**
* Completely resets the emote statistics in {@link Guild}. This will purge all emote usages and delete all {@link TrackedEmote}
* of this {@link Guild}
* @param guild The {@link Guild} to reset the emote statistics for
*/
void resetEmoteStats(Guild guild);
/**
* Disables emote tracking for *every* {@link TrackedEmote} within the {@link Guild} individually. Effectively disabling
* emote tracking within the server.
* @param guild The {@link Guild} to disable emote tracking for
*/
void disableEmoteTracking(Guild guild);
}

View File

@@ -6,11 +6,58 @@ import dev.sheldan.abstracto.statistic.emotes.model.database.TrackedEmote;
import java.time.Instant;
/**
* Service responsible to provide operations on {@link dev.sheldan.abstracto.statistic.emotes.model.database.UsedEmote}
*/
public interface UsedEmoteService {
/**
* Retrieves the {@link EmoteStatsModel} for the {@link AServer} since {@link Instant}.
* This {@link EmoteStatsModel} will contain all {@link TrackedEmote} from the server
* @param server The {@link AServer} to retrieve the emote stats for
* @param since Emote stats should be younger than this {@link Instant}. Only the date portion is considered.
* @return An {@link EmoteStatsModel} containing the statistics split by animated and static {@link net.dv8tion.jda.api.entities.Emote}
*/
EmoteStatsModel getEmoteStatsForServerSince(AServer server, Instant since);
/**
* Retrieves the {@link EmoteStatsModel} for the {@link AServer} since {@link Instant}.
* This {@link EmoteStatsModel} will contain only deleted {@link TrackedEmote} from the server
* @param server The {@link AServer} to retrieve the emote stats for
* @param since Emote stats should be younger than this {@link Instant}. Only the date portion is considered.
* @return An {@link EmoteStatsModel} containing the statistics split by animated and static {@link net.dv8tion.jda.api.entities.Emote}
*/
EmoteStatsModel getDeletedEmoteStatsForServerSince(AServer server, Instant since);
/**
* Retrieves the {@link EmoteStatsModel} for the {@link AServer} since {@link Instant}.
* This {@link EmoteStatsModel} will contain only external {@link TrackedEmote} from the server
* @param server The {@link AServer} to retrieve the emote stats for
* @param since Emote stats should be younger than this {@link Instant}. Only the date portion is considered.
* @return An {@link EmoteStatsModel} containing the statistics split by animated and static {@link net.dv8tion.jda.api.entities.Emote}
*/
EmoteStatsModel getExternalEmoteStatsForServerSince(AServer server, Instant since);
/**
* Retrieves the {@link EmoteStatsModel} for the {@link AServer} since {@link Instant}.
* This {@link EmoteStatsModel} will contain only active {@link TrackedEmote} from the server. These are emotes which are still present
* the {@link net.dv8tion.jda.api.entities.Guild}
* @param server The {@link AServer} to retrieve the emote stats for
* @param since Emote stats should be younger than this {@link Instant}. Only the date portion is considered.
* @return An {@link EmoteStatsModel} containing the statistics split by animated and static {@link net.dv8tion.jda.api.entities.Emote}
*/
EmoteStatsModel getActiveEmoteStatsForServerSince(AServer server, Instant since);
/**
* Removes all {@link dev.sheldan.abstracto.statistic.emotes.model.database.UsedEmote} for the given {@link TrackedEmote} which are younger
* than the given {@link Instant}
* @param emote The {@link TrackedEmote} which should have its usages removed
* @param since {@link dev.sheldan.abstracto.statistic.emotes.model.database.UsedEmote} younger than this {@link Instant} shold be remoed. Only the date porition is considered.
*/
void purgeEmoteUsagesSince(TrackedEmote emote, Instant since);
/**
* Removes *all* {@link dev.sheldan.abstracto.statistic.emotes.model.database.UsedEmote} for the given {@link TrackedEmote}.
* @param emote The {@link TrackedEmote} which should have its usages removed
*/
void purgeEmoteUsages(TrackedEmote emote);
}

View File

@@ -1,36 +1,195 @@
package dev.sheldan.abstracto.statistic.emotes.service.management;
import dev.sheldan.abstracto.core.models.ServerSpecificId;
import dev.sheldan.abstracto.core.models.database.AServer;
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 net.dv8tion.jda.api.entities.Emote;
import net.dv8tion.jda.api.entities.Guild;
import java.util.List;
import java.util.Optional;
/**
* Service responsible for managing {@link TrackedEmote} instances in the database
*/
public interface TrackedEmoteManagementService {
/**
* Creates and persists a {@link TrackedEmote} for which tracking is enabled with the given individual parameters
* @param emoteId The ID of the {@link Emote} to track
* @param emoteName The name of the {@link Emote} to track
* @param animated Whether or not the {@link Emote} to track is animated
* @param server The {@link AServer} for which the {@link Emote} should be tracked
* @return The created {@link TrackedEmote} instance in the database
*/
TrackedEmote createTrackedEmote(Long emoteId, String emoteName, Boolean animated, AServer server);
/**
* Creates and persists a {@link TrackedEmote} for which tracking is enabled based on the given {@link Emote} and {@link Guild}
* @param emote The {@link Emote} to be used to create a {@link TrackedEmote}
* @param guild The {@link Guild} for which the emote should be tracked for
* @return The created {@link TrackedEmote} instance in the database
*/
TrackedEmote createTrackedEmote(Emote emote, Guild guild);
/**
* Creates and persist a {@link TrackedEmote} for which tracking is enabled based on the given {@link Emote} and {@link Guild}
* @param emote The {@link Emote} to be used to create a {@link TrackedEmote}
* @param guild The {@link Guild} for which the emote should be tracked for
* @param external Whether or not the emote is external
* @return The created {@link TrackedEmote} instance in the database
*/
TrackedEmote createTrackedEmote(Emote emote, Guild guild, boolean external);
/**
* Creates and persis a {@link TrackedEmote} based ont he given parameters
* @param emoteId The ID of an {@link Emote}
* @param emoteName The name of an {@link Emote}
* @param animated Whether or not the {@link Emote} is enabled
* @param tracked Whether or not the {@link TrackedEmote} should have tracking enabled
* @param server The {@link AServer} for which the {@link TrackedEmote} should be created
* @return The created {@link TrackedEmote} instance in the database
*/
TrackedEmote createTrackedEmote(Long emoteId, String emoteName, Boolean animated, Boolean tracked, AServer server);
TrackedEmote createExternalEmote(Long emoteId, String emoteName, String externalUrl, Boolean animated, AServer server);
/**
* Creates an {@link TrackedEmote} based on the parameters which is external
* @param emoteId The ID of an {@link Emote}
* @param emoteName the name of an {@link Emote}
* @param externalUrl The URL of the {@link Emote} which should be stored
* @param animated Whether or not the {@link Emote} is external
* @param server The {@link AServer} for which the {@link TrackedEmote} should be created
* @param trackingEnabled Whether or not the {@link TrackedEmote} should have tracking enabled
* @return The created {@link TrackedEmote} instance in the database
*/
TrackedEmote createExternalEmote(Long emoteId, String emoteName, String externalUrl, Boolean animated, AServer server, boolean trackingEnabled);
/**
* Creates an {@link TrackedEmote} based on the parameters which is not being tracked
* @param emoteId The ID of an {@link Emote}
* @param emoteName The name of an {@link Emote}
* @param animated Whether or not the {@link Emote} is animated
* @param server The {@link AServer} for which the {@link TrackedEmote} should be created
* @return The created {@link TrackedEmote} instance in the database
*/
TrackedEmote createNotTrackedEmote(Long emoteId, String emoteName, Boolean animated, AServer server);
TrackedEmote createExternalEmote(PersistingEmote persistingEmote);
TrackedEmote createExternalEmote(Emote emote, Guild guild);
/**
* Creates an {@link TrackedEmote} based on the {@link PersistingEmote} which is being tracked
* @param persistingEmote The {@link PersistingEmote} to create the {@link TrackedEmote} based of
* @return The created {@link TrackedEmote} instance in the database
*/
TrackedEmote createExternalTrackedEmote(PersistingEmote persistingEmote);
/**
* Creates an external {@link TrackedEmote} based on the {@link Emote} and the {@link Guild}
* @param emote The {@link Emote} to be used to create an external {@link TrackedEmote}
* @param guild The {@link Guild} for which the emote should be tracked for
* @return The create {@link TrackedEmote} instance in the database
*/
TrackedEmote createExternalTrackedEmote(Emote emote, Guild guild);
/**
* Marks the {@link TrackedEmote} identified by serverId and emoteId as deleted
* @param serverId The ID of the server to mark the {@link TrackedEmote} as deleted
* @param emoteId The ID of the {@link Emote} to mark the {@link TrackedEmote} as deleted
* @throws TrackedEmoteNotFoundException if no {@link TrackedEmote} with the given IDs can be found
*/
void markAsDeleted(Long serverId, Long emoteId);
void markAsDeleted(TrackedEmote trackedemote);
/**
* Marks the given {@link TrackedEmote} as deleted
* @param trackedEmote The {@link TrackedEmote} which should be marked as deleted
*/
void markAsDeleted(TrackedEmote trackedEmote);
/**
* Retrieves a {@link TrackedEmote} by the given emoteID and serverID
* @param emoteId The ID of the {@link AServer} so search for
* @param serverId The ID Of the {@link Emote} to search for
* @return The found {@link TrackedEmote} instance if, one exists
* @throws TrackedEmoteNotFoundException if no {@link TrackedEmote} with the given IDs can be found
*/
TrackedEmote loadByEmoteId(Long emoteId, Long serverId);
/**
* Loads a {@link TrackedEmote} by the given {@link Emote}. The ID necessary for the server is the {@link Guild} from the emote.
* The {@link Emote} must containing a {@link Guild} object, this is not guaranteed, but this implementation relies on it.
* @param emote The {@link Emote} to find a {@link TrackedEmote} for
* @return The {@link TrackedEmote} which was found
* @throws TrackedEmoteNotFoundException if no {@link TrackedEmote} with the given IDs can be found
*/
TrackedEmote loadByEmote(Emote emote);
/**
* Checks whether or not a {@link TrackedEmote} with the given emote ID and server ID exists
* @param emoteId The ID of an {@link Emote} to check
* @param serverId the ID of an {@link AServer} to check
* @return Whether or not a {@link TrackedEmote} with the given IDs exists
*/
boolean trackedEmoteExists(Long emoteId, Long serverId);
TrackedEmote loadByTrackedEmoteServer(TrackedEmoteServer trackedEmoteServer);
/**
* Loads a {@link TrackedEmote} based on its composite keys represented by a {@link ServerSpecificId}
* @param trackedEmoteServer The {@link ServerSpecificId} to retrieve a {@link TrackedEmote} from
* @return The found {@link TrackedEmote} based on the given parameters
* @throws TrackedEmoteNotFoundException if no {@link TrackedEmote} with the given {@link ServerSpecificId} was found
*/
TrackedEmote loadByTrackedEmoteServer(ServerSpecificId trackedEmoteServer);
/**
* Searches for a {@link TrackedEmote} by the given emoteId and serverId and returns an {@link Optional} containing the value, if any.
* @param emoteId The ID of the {@link Emote} to search for
* @param serverId The ID of the {@link AServer} to search for
* @return An {@link Optional} containing a {@link TrackedEmote} if it exists, empty otherwise
*/
Optional<TrackedEmote> loadByEmoteIdOptional(Long emoteId, Long serverId);
/**
* Retrieves all {@link TrackedEmote} for a {@link AServer}, which are not yet deleted and not external
* @param server The {@link AServer} to retrieve the active {@link TrackedEmote} for
* @return A list of {@link TrackedEmote} which are currently considered active from the {@link AServer}
*/
List<TrackedEmote> getAllActiveTrackedEmoteForServer(AServer server);
/**
* Retrieves all {@link TrackedEmote} for an ID of a {@link AServer}, which are not yet deleted and not external
* @param serverId The ID of an {@link AServer} ro retrieve the active {@link TrackedEmote} for
* @return A list of {@link TrackedEmote} which are currently considered active from the {@link AServer} with the ID
*/
List<TrackedEmote> getAllActiveTrackedEmoteForServer(Long serverId);
/**
* Retrieves *all* tracking enabled {@link TrackedEmote} for an ID of a {@link AServer}, with the option to also retrieve the ones for which tracking is disable
* @param serverId The ID of an {@link AServer} to retrieve the {@link TrackedEmote} for
* @param showTrackingDisabledEmotes Whether or not tracking disabled {@link TrackedEmote} should be retrieved as well
* @return A list of {@link TrackedEmote} from an {@link AServer} with the given ID
*/
List<TrackedEmote> getTrackedEmoteForServer(Long serverId, Boolean showTrackingDisabledEmotes);
/**
* Changes the name of the given {@link TrackedEmote} to a new value
* @param emote The {@link TrackedEmote} to change the name of
* @param name The new name to change to
*/
void changeName(TrackedEmote emote, String name);
/**
* Disables the tracking of a {@link TrackedEmote}
* @param emote The {@link TrackedEmote} to disable the tracking of
*/
void disableTrackedEmote(TrackedEmote emote);
/**
* Enables the tracking of a {@link TrackedEmote}
* @param emote The {@link TrackedEmote} to enable the tracking of
*/
void enableTrackedEmote(TrackedEmote emote);
/**
* Deletes the given {@link TrackedEmote}
* @param emote The {@link TrackedEmote} to delete
*/
void deleteTrackedEmote(TrackedEmote emote);
}

View File

@@ -9,13 +9,70 @@ import java.time.Instant;
import java.util.List;
import java.util.Optional;
/**
* Service responsible for creating/updating/deleting {@link UsedEmote} instances in the database
*/
public interface UsedEmoteManagementService {
/**
* Loads an {@link Optional} containing a {@link UsedEmote} for the particular {@link TrackedEmote} for the current day.
* The {@link Optional} is empty, if none exists.
* @param trackedEmote The {@link TrackedEmote} to search a {@link UsedEmote} for today
* @return An {@link Optional} containing a {@link UsedEmote}, if it exists for the current day
*/
Optional<UsedEmote> loadUsedEmoteForTrackedEmoteToday(TrackedEmote trackedEmote);
/**
* Creates and persists and instance of {@link UsedEmote} from the given {@link TrackedEmote}, with the defined count and the current date.
* @param trackedEmote The {@link TrackedEmote} for which to create a {@link UsedEmote} for
* @param count The amount of usages for the {@link UsedEmote}
* @return The created {@link UsedEmote} instance int he database
*/
UsedEmote createEmoteUsageForToday(TrackedEmote trackedEmote, Long count);
/**
* Loads {@link UsedEmote} for the {@link AServer} which are newer than the given {@link Instant}
* @param server The {@link AServer} to retrieve the {@link UsedEmote} for
* @param since The {@link Instant} since when the emote stats should be retrieved. Only the date portion is considered.
* @return A list of {@link UsedEmote} from the {@link AServer} newer than the given {@link Instant}
*/
List<UsedEmote> loadEmoteUsagesForServerSince(AServer server, Instant since);
/**
* Load {@link EmoteStatsResult} from the {@link AServer} for all {@link TrackedEmote} which are newer than {@link Instant}
* @param server The {@link AServer} to retrieve the emote statistics for
* @param since Emote stats should be younger than this {@link Instant}. Only the date portion is considered.
* @return A list of {@link EmoteStatsResult} from the {@link AServer} newer than the given {@link Instant} for all {@link TrackedEmote}
*/
List<EmoteStatsResult> loadAllEmoteStatsForServerSince(AServer server, Instant since);
/**
* Load {@link EmoteStatsResult} from the {@link AServer} for {@link TrackedEmote} which were deleted and newer than {@link Instant}
* @param server The {@link AServer} to retrieve the emote statistics for
* @param since Emote stats should be younger than this {@link Instant}. Only the date portion is considered.
* @return A list of {@link EmoteStatsResult} from the {@link AServer} newer than the given {@link Instant} for all deleted {@link TrackedEmote}
*/
List<EmoteStatsResult> loadDeletedEmoteStatsForServerSince(AServer server, Instant since);
/**
* Load {@link EmoteStatsResult} from the {@link AServer} for {@link TrackedEmote} which are external and newer than {@link Instant}
* @param server The {@link AServer} to retrieve the emote statistic for
* @param since Emote stats should be younger than this {@link Instant}. Only the date portion is considered.
* @return A list of {@link EmoteStatsResult} from the {@link AServer} newer than the given {@link Instant} for all external {@link TrackedEmote}
*/
List<EmoteStatsResult> loadExternalEmoteStatsForServerSince(AServer server, Instant since);
/**
* Load {@link EmoteStatsResult} from the {@link AServer} for {@link TrackedEmote} which are active and newer than {@link Instant}
* @param server The {@link AServer} to retrieve the emote statistic for
* @param since Emote stats should be younger than this {@link Instant}. Only the date portion is considered.
* @return A list of {@link EmoteStatsResult} from the {@link AServer} newer than the given {@link Instant} for all active {@link TrackedEmote}
*/
List<EmoteStatsResult> loadActiveEmoteStatsForServerSince(AServer server, Instant since);
/**
* Deletes all emote usages for the {@link TrackedEmote} which are younger than the given {@link Instant}
* @param emote The {@link TrackedEmote} to remove the usages for
* @param since All emote stats which are newer than this {@link Instant} will be deleted
*/
void purgeEmoteUsagesSince(TrackedEmote emote, Instant since);
}