getRemovalTasks() {
.all();
}
+ /**
+ * Cleans up GDPR requests that are older than the configured number of days.
+ */
public void cleanupRequests() {
Query.query("""
DELETE FROM gdpr_log
@@ -52,17 +68,22 @@ public void cleanupRequests() {
.update();
}
+ /**
+ * Creates a new GDPR user request.
+ *
+ * @param user the user requesting their data
+ * @return the GDPR user request
+ */
public GdprUser request(User user) {
return new GdprUser(user);
}
/**
- * Get a list of {@link GdprUser}s which have requested their data.
- *
- * Only users which are known to the provided shard manager will be returned.
+ * Retrieves a list of GDPR users who have requested their data.
+ * Only users known to the provided shard manager will be returned.
*
- * @param shardManager shardmanager to resolve users.
- * @return list of users
+ * @param shardManager the shard manager to resolve users
+ * @return the list of GDPR users
*/
public List getReportRequests(ShardManager shardManager) {
return Query
@@ -70,7 +91,7 @@ public List getReportRequests(ShardManager shardManager) {
SELECT user_id
FROM gdpr_log
WHERE received IS NULL
- AND last_attempt < now() - (least(48, attempts) || ' HOURS')::INTERVAL
+ AND last_attempt < now() - (least(48, attempts) || ' HOURS')::INTERVAL
""")
.single()
.map(rs -> GdprUser.build(rs, shardManager))
diff --git a/src/main/java/de/chojo/repbot/dao/access/gdpr/GdprUser.java b/src/main/java/de/chojo/repbot/dao/access/gdpr/GdprUser.java
index 3a8eda4f9..05bedf3c1 100644
--- a/src/main/java/de/chojo/repbot/dao/access/gdpr/GdprUser.java
+++ b/src/main/java/de/chojo/repbot/dao/access/gdpr/GdprUser.java
@@ -25,15 +25,31 @@
import static de.chojo.sadu.queries.api.query.Query.query;
import static org.slf4j.LoggerFactory.getLogger;
+/**
+ * Provides GDPR-related data access methods for users.
+ */
public class GdprUser {
private static final Logger log = getLogger(GdprUser.class);
private final User user;
+ /**
+ * Constructs a new GdprUser instance.
+ *
+ * @param user the User instance
+ */
public GdprUser(User user) {
this.user = user;
}
+ /**
+ * Builds a GdprUser instance from the given database row and shard manager.
+ *
+ * @param rs the database row
+ * @param shardManager the shard manager
+ * @return the GdprUser instance, or null if the user could not be retrieved
+ * @throws SQLException if a database access error occurs
+ */
@Nullable
public static GdprUser build(Row rs, ShardManager shardManager) throws SQLException {
try {
@@ -50,6 +66,11 @@ public static GdprUser build(Row rs, ShardManager shardManager) throws SQLExcept
}
}
+ /**
+ * Queues the user for deletion by adding them to the cleanup schedule.
+ *
+ * @return true if the user was successfully queued for deletion, false otherwise
+ */
public boolean queueDeletion() {
log.info("User {} requested deletion of their data", userId());
return query("""
@@ -64,6 +85,11 @@ ON CONFLICT(guild_id, user_id)
.changed();
}
+ /**
+ * Requests the deletion of the user's data.
+ *
+ * @return true if the request was successful, false otherwise
+ */
public boolean request() {
try (var conn = QueryConfiguration.getDefault().withSingleTransaction()) {
var res = conn.query("""
@@ -85,18 +111,29 @@ ON CONFLICT(user_id)
}
}
+ /**
+ * Marks the user's GDPR request as sent.
+ */
public void requestSend() {
query("UPDATE gdpr_log SET received = now(), last_attempt = now() WHERE user_id = ?")
.single(call().bind(userId()))
.update();
}
+ /**
+ * Marks the user's GDPR request as failed.
+ */
public void requestSendFailed() {
query("UPDATE gdpr_log SET attempts = attempts + 1, last_attempt = now() WHERE user_id = ?")
.single(call().bind(userId()))
.update();
}
+ /**
+ * Retrieves the user's data.
+ *
+ * @return an Optional containing the user's data, or an empty Optional if the data could not be retrieved
+ */
public Optional userData() {
return query("SELECT aggregate_user_data(?)")
.single(call().bind(userId()))
@@ -166,6 +203,11 @@ public boolean sendData() {
return true;
}
+ /**
+ * Retrieves the ID of the user associated with this instance.
+ *
+ * @return the user ID
+ */
private long userId() {
return user.getIdLong();
}
diff --git a/src/main/java/de/chojo/repbot/dao/access/gdpr/RemovalTask.java b/src/main/java/de/chojo/repbot/dao/access/gdpr/RemovalTask.java
index 2c560e0d3..7f58d6ed4 100644
--- a/src/main/java/de/chojo/repbot/dao/access/gdpr/RemovalTask.java
+++ b/src/main/java/de/chojo/repbot/dao/access/gdpr/RemovalTask.java
@@ -15,26 +15,52 @@
import static de.chojo.sadu.queries.api.call.Call.call;
import static org.slf4j.LoggerFactory.getLogger;
+/**
+ * Represents a task for removing user or guild data for GDPR compliance.
+ */
public final class RemovalTask {
private static final Logger log = getLogger(RemovalTask.class);
private final long taskId;
private final long guildId;
private final long userId;
+ /**
+ * Constructs a RemovalTask with the specified task ID, guild ID, and user ID.
+ *
+ * @param taskId the task ID
+ * @param guildId the guild ID
+ * @param userId the user ID
+ */
public RemovalTask(long taskId, long guildId, long userId) {
this.taskId = taskId;
this.guildId = guildId;
this.userId = userId;
}
+ /**
+ * Builds a RemovalTask from the given database row.
+ *
+ * @param rs the database row
+ * @return a new RemovalTask instance
+ * @throws SQLException if a database access error occurs
+ */
public static RemovalTask build(Row rs) throws SQLException {
return new RemovalTask(rs.getLong("task_id"), rs.getLong("guild_id"), rs.getLong("user_id"));
}
+ /**
+ * Executes an anonymous removal task for the specified guild ID and user ID.
+ *
+ * @param guildId the guild ID
+ * @param userId the user ID
+ */
public static void anonymExecute(long guildId, long userId) {
new RemovalTask(-1L, guildId, userId).executeRemovalTask();
}
+ /**
+ * Executes the removal task, deleting user or guild data from the database.
+ */
public void executeRemovalTask() {
try (var conn = QueryConfiguration.getDefault().withSingleTransaction()) {
if (userId() == 0) {
@@ -70,14 +96,29 @@ public void executeRemovalTask() {
}
}
+ /**
+ * Gets the task ID.
+ *
+ * @return the task ID
+ */
public long taskId() {
return taskId;
}
+ /**
+ * Gets the guild ID.
+ *
+ * @return the guild ID
+ */
public long guildId() {
return guildId;
}
+ /**
+ * Gets the user ID.
+ *
+ * @return the user ID
+ */
public long userId() {
return userId;
}
diff --git a/src/main/java/de/chojo/repbot/dao/access/guild/Cleanup.java b/src/main/java/de/chojo/repbot/dao/access/guild/Cleanup.java
index fe47822d7..b07dd0188 100644
--- a/src/main/java/de/chojo/repbot/dao/access/guild/Cleanup.java
+++ b/src/main/java/de/chojo/repbot/dao/access/guild/Cleanup.java
@@ -14,13 +14,24 @@
import static de.chojo.sadu.queries.api.call.Call.call;
import static de.chojo.sadu.queries.api.query.Query.query;
+/**
+ * Class responsible for handling cleanup operations for a guild.
+ */
public class Cleanup implements GuildHolder {
private final RepGuild repGuild;
+ /**
+ * Constructs a Cleanup instance with the specified RepGuild.
+ *
+ * @param repGuild the RepGuild instance
+ */
public Cleanup(RepGuild repGuild) {
this.repGuild = repGuild;
}
+ /**
+ * Prompts self-cleanup by inserting a record into the self_cleanup table.
+ */
public void selfCleanupPrompt() {
query("""
INSERT INTO self_cleanup(guild_id) VALUES(?)
@@ -29,6 +40,11 @@ INSERT INTO self_cleanup(guild_id) VALUES(?)
.update();
}
+ /**
+ * Retrieves the time when the cleanup was prompted.
+ *
+ * @return an Optional containing the LocalDateTime of the prompt, if present
+ */
public Optional getCleanupPromptTime() {
return query("""
SELECT prompted FROM self_cleanup WHERE guild_id = ?
@@ -38,6 +54,9 @@ public Optional getCleanupPromptTime() {
.first();
}
+ /**
+ * Marks the cleanup as done by deleting the record from the self_cleanup table.
+ */
public void cleanupDone() {
query("""
DELETE FROM self_cleanup WHERE guild_id = ?
@@ -46,11 +65,21 @@ public void cleanupDone() {
.update();
}
+ /**
+ * Gets the Guild associated with this Cleanup instance.
+ *
+ * @return the Guild
+ */
@Override
public Guild guild() {
return repGuild.guild();
}
+ /**
+ * Gets the ID of the Guild associated with this Cleanup instance.
+ *
+ * @return the Guild ID
+ */
@Override
public long guildId() {
return repGuild.guildId();
diff --git a/src/main/java/de/chojo/repbot/dao/access/guild/Gdpr.java b/src/main/java/de/chojo/repbot/dao/access/guild/Gdpr.java
index d5f4d32e5..2e7f82e65 100644
--- a/src/main/java/de/chojo/repbot/dao/access/guild/Gdpr.java
+++ b/src/main/java/de/chojo/repbot/dao/access/guild/Gdpr.java
@@ -13,24 +13,45 @@
import static de.chojo.sadu.queries.api.query.Query.query;
import static org.slf4j.LoggerFactory.getLogger;
+/**
+ * Provides GDPR-related data access methods for guilds.
+ */
public class Gdpr implements GuildHolder {
private final RepGuild repGuild;
private static final Logger log = getLogger(Gdpr.class);
+ /**
+ * Constructs a new Gdpr instance.
+ *
+ * @param repGuild the RepGuild instance
+ */
public Gdpr(RepGuild repGuild) {
this.repGuild = repGuild;
}
+ /**
+ * Retrieves the guild associated with this instance.
+ *
+ * @return the guild
+ */
@Override
public Guild guild() {
return repGuild.guild();
}
+ /**
+ * Retrieves the ID of the guild associated with this instance.
+ *
+ * @return the guild ID
+ */
@Override
public long guildId() {
return repGuild.guildId();
}
+ /**
+ * Queues the guild for deletion by adding it to the cleanup schedule.
+ */
public void queueDeletion() {
if (query("""
INSERT INTO
@@ -46,6 +67,9 @@ ON CONFLICT(guild_id, user_id)
}
}
+ /**
+ * Dequeues the guild from deletion by removing it from the cleanup schedule.
+ */
public void dequeueDeletion() {
if (query("DELETE FROM cleanup_schedule WHERE guild_id = ? AND user_id = 0;")
.single(call().bind(guildId()))
diff --git a/src/main/java/de/chojo/repbot/dao/access/guild/RepGuild.java b/src/main/java/de/chojo/repbot/dao/access/guild/RepGuild.java
index 916087574..6b2f47bf0 100644
--- a/src/main/java/de/chojo/repbot/dao/access/guild/RepGuild.java
+++ b/src/main/java/de/chojo/repbot/dao/access/guild/RepGuild.java
@@ -21,6 +21,9 @@
import static de.chojo.sadu.queries.api.call.Call.call;
import static de.chojo.sadu.queries.api.query.Query.query;
+/**
+ * Represents a guild with reputation and settings management.
+ */
public class RepGuild implements GuildHolder {
private static final Cache CLEANUPS = CacheBuilder.newBuilder()
.expireAfterAccess(2, TimeUnit.MINUTES).build();
@@ -31,6 +34,12 @@ public class RepGuild implements GuildHolder {
private Guild guild;
private final Configuration configuration;
+ /**
+ * Constructs a RepGuild with the specified guild and configuration.
+ *
+ * @param guild the guild
+ * @param configuration the configuration
+ */
public RepGuild(Guild guild, Configuration configuration) {
super();
this.configuration = configuration;
@@ -39,15 +48,30 @@ public RepGuild(Guild guild, Configuration configuration) {
this.guild = guild;
}
+ /**
+ * Returns the guild.
+ *
+ * @return the guild
+ */
public Guild guild() {
return guild;
}
+ /**
+ * Returns the guild ID.
+ *
+ * @return the guild ID
+ */
@Override
public long guildId() {
return guild.getIdLong();
}
+ /**
+ * Returns the GDPR settings for the guild.
+ *
+ * @return the GDPR settings
+ */
public Gdpr gdpr() {
try {
return GDPR.get(guildId(), () -> new Gdpr(this));
@@ -56,37 +80,41 @@ public Gdpr gdpr() {
}
}
+ /**
+ * Refreshes the guild with the specified guild.
+ *
+ * @param guild the guild
+ * @return the refreshed RepGuild
+ */
public RepGuild refresh(Guild guild) {
this.guild = guild;
return this;
}
- //Todo: We don't actually know how many users are on a guild and saved in the database. At some point we might want to add some pagination here.
-
/**
- * A list of user ids of all users which are connected to this guild.
+ * Returns a list of user IDs of all users connected to this guild.
*
- * @return list of user ids
+ * @return list of user IDs
*/
public List userIds() {
return query("""
SELECT
- user_id AS user_id
+ user_id AS user_id
FROM
- (
- SELECT
- donor_id AS user_id
- FROM
- reputation_log
- WHERE guild_id = ?
- UNION
- DISTINCT
- SELECT
- receiver_id AS user_id
- FROM
- reputation_log
- WHERE guild_id = ?
- ) users
+ (
+ SELECT
+ donor_id AS user_id
+ FROM
+ reputation_log
+ WHERE guild_id = ?
+ UNION
+ DISTINCT
+ SELECT
+ receiver_id AS user_id
+ FROM
+ reputation_log
+ WHERE guild_id = ?
+ ) users
WHERE user_id != 0
""")
.single(call().bind(guildId()).bind(guildId()))
@@ -94,14 +122,29 @@ public List userIds() {
.all();
}
+ /**
+ * Returns the reputation management for the guild.
+ *
+ * @return the reputation management
+ */
public Reputation reputation() {
return reputation;
}
+ /**
+ * Returns the settings for the guild.
+ *
+ * @return the settings
+ */
public Settings settings() {
return settings;
}
+ /**
+ * Returns the cleanup settings for the guild.
+ *
+ * @return the cleanup settings
+ */
public Cleanup cleanup() {
try {
return CLEANUPS.get(guildId(), () -> new Cleanup(this));
@@ -110,10 +153,20 @@ public Cleanup cleanup() {
}
}
+ /**
+ * Checks if the guild is identified by ID.
+ *
+ * @return true if the guild is identified by ID, false otherwise
+ */
public boolean isById() {
return guild == null;
}
+ /**
+ * Returns a string representation of the RepGuild.
+ *
+ * @return a string representation of the RepGuild
+ */
@Override
public String toString() {
return "RepGuild{" +
@@ -121,12 +174,23 @@ public String toString() {
'}';
}
+ /**
+ * Loads the guild using the specified shard manager.
+ *
+ * @param shardManager the shard manager
+ * @return the loaded RepGuild
+ */
public RepGuild load(ShardManager shardManager) {
if (guild != null) return this;
guild = shardManager.getGuildById(guildId());
return this;
}
+ /**
+ * Returns the configuration for the guild.
+ *
+ * @return the configuration
+ */
public Configuration configuration() {
return configuration;
}
diff --git a/src/main/java/de/chojo/repbot/dao/access/guild/RepGuildId.java b/src/main/java/de/chojo/repbot/dao/access/guild/RepGuildId.java
index 81511fc62..0d4e4379c 100644
--- a/src/main/java/de/chojo/repbot/dao/access/guild/RepGuildId.java
+++ b/src/main/java/de/chojo/repbot/dao/access/guild/RepGuildId.java
@@ -9,14 +9,28 @@
import javax.sql.DataSource;
+/**
+ * Represents a guild with a specific ID in the reputation bot.
+ */
public class RepGuildId extends RepGuild {
private final long guildId;
+ /**
+ * Constructs a RepGuildId with the specified guild ID and configuration.
+ *
+ * @param guildId the ID of the guild
+ * @param configuration the configuration
+ */
public RepGuildId(long guildId, Configuration configuration) {
super(null, configuration);
this.guildId = guildId;
}
+ /**
+ * Returns the ID of the guild.
+ *
+ * @return the guild ID
+ */
@Override
public long guildId() {
return guildId;
diff --git a/src/main/java/de/chojo/repbot/dao/access/guild/reputation/sub/Analyzer.java b/src/main/java/de/chojo/repbot/dao/access/guild/reputation/sub/Analyzer.java
index ffd94b47f..06d361695 100644
--- a/src/main/java/de/chojo/repbot/dao/access/guild/reputation/sub/Analyzer.java
+++ b/src/main/java/de/chojo/repbot/dao/access/guild/reputation/sub/Analyzer.java
@@ -32,8 +32,15 @@
import static de.chojo.sadu.queries.api.query.Query.query;
import static org.slf4j.LoggerFactory.getLogger;
+/**
+ * Class for analyzing and logging reputation-related data.
+ */
public class Analyzer implements GuildHolder {
private static final Logger log = getLogger(Analyzer.class);
+
+ /**
+ * ObjectMapper instance for JSON serialization and deserialization.
+ */
public static final ObjectMapper MAPPER = JsonMapper.builder()
.configure(MapperFeature.ALLOW_FINAL_FIELDS_AS_MUTATORS, true)
.build()
@@ -43,10 +50,22 @@ public class Analyzer implements GuildHolder {
private final Reputation reputation;
+ /**
+ * Constructs an Analyzer with the specified Reputation instance.
+ *
+ * @param reputation the Reputation instance
+ */
public Analyzer(Reputation reputation) {
this.reputation = reputation;
}
+ /**
+ * Logs the analyzer result for a given message.
+ *
+ * @param message the message
+ * @param analyzerResult the analyzer result
+ * @return the analyzer result
+ */
public AnalyzerResult log(Message message, AnalyzerResult analyzerResult) {
String resultString;
try {
@@ -67,6 +86,12 @@ ON CONFLICT (guild_id, message_id)
return analyzerResult;
}
+ /**
+ * Logs the submit result for a given message.
+ *
+ * @param message the message
+ * @param result the submit result
+ */
public void log(Message message, SubmitResult result) {
String resultString;
try {
@@ -84,6 +109,12 @@ public void log(Message message, SubmitResult result) {
.insert();
}
+ /**
+ * Retrieves the analyzer trace for a given message ID.
+ *
+ * @param messageId the message ID
+ * @return an optional containing the analyzer trace if found, otherwise empty
+ */
public Optional get(long messageId) {
var resultEntry = getResults(messageId);
@@ -94,7 +125,12 @@ public Optional get(long messageId) {
return Optional.of(new AnalyzerTrace(resultEntry.orElse(null), submitResults));
}
-
+ /**
+ * Retrieves the result entry for a given message ID.
+ *
+ * @param messageId the message ID
+ * @return an optional containing the result entry if found, otherwise empty
+ */
private Optional getResults(long messageId) {
return query("""
SELECT guild_id, channel_id, message_id, result, analyzed
@@ -114,6 +150,12 @@ private Optional getResults(long messageId) {
}).first();
}
+ /**
+ * Retrieves the submit result entries for a given message ID.
+ *
+ * @param messageId the message ID
+ * @return a list of submit result entries
+ */
private List getSubmitResults(long messageId) {
return query("""
SELECT guild_id, channel_id, message_id, result, submitted
@@ -134,11 +176,21 @@ private List getSubmitResults(long messageId) {
}).all();
}
+ /**
+ * Returns the guild associated with this analyzer.
+ *
+ * @return the guild
+ */
@Override
public Guild guild() {
return reputation.guild();
}
+ /**
+ * Returns the guild ID associated with this analyzer.
+ *
+ * @return the guild ID
+ */
@Override
public long guildId() {
return reputation.guildId();
diff --git a/src/main/java/de/chojo/repbot/dao/access/guild/reputation/sub/Log.java b/src/main/java/de/chojo/repbot/dao/access/guild/reputation/sub/Log.java
index 1e7d11c03..8112b4251 100644
--- a/src/main/java/de/chojo/repbot/dao/access/guild/reputation/sub/Log.java
+++ b/src/main/java/de/chojo/repbot/dao/access/guild/reputation/sub/Log.java
@@ -19,9 +19,17 @@
import static de.chojo.sadu.queries.api.call.Call.call;
import static de.chojo.sadu.queries.api.query.Query.query;
-public class Log implements GuildHolder {
+/**
+ * Handles logging of reputation-related actions for a guild.
+ */
+public class Log implements GuildHolder {
private final Reputation reputation;
+ /**
+ * Constructs a new Log instance with the specified Reputation provider.
+ *
+ * @param reputation the Reputation provider
+ */
public Log(Reputation reputation) {
this.reputation = reputation;
}
@@ -29,13 +37,21 @@ public Log(Reputation reputation) {
/**
* Get the last log entries for reputation received by the user.
*
- * @param user user
- * @return sorted list of entries. the most recent first.
+ * @param user the user
+ * @param pageSize the number of entries per page
+ * @return a ReputationLogAccess object for paginated access to the log entries
*/
public ReputationLogAccess getUserReceivedLog(User user, int pageSize) {
return new ReputationLogAccess(() -> getUserReceivedLogPages(user, pageSize), page -> getUserReceivedLogPage(user, pageSize, page));
}
+ /**
+ * Get the last log entries for reputation donated by the user.
+ *
+ * @param user the user
+ * @param pageSize the number of entries per page
+ * @return a ReputationLogAccess object for paginated access to the log entries
+ */
public ReputationLogAccess userDonatedLog(User user, int pageSize) {
return new ReputationLogAccess(() -> getUserDonatedLogPages(user, pageSize), page -> getUserDonatedLogPage(user, pageSize, page));
}
@@ -43,8 +59,10 @@ public ReputationLogAccess userDonatedLog(User user, int pageSize) {
/**
* Get the last log entries for reputation received by the user.
*
- * @param user user
- * @return sorted list of entries. the most recent first.
+ * @param user the user
+ * @param pageSize the number of entries per page
+ * @param page the page number
+ * @return a list of ReputationLogEntry objects
*/
private List getUserReceivedLogPage(User user, int pageSize, int page) {
return getLog("receiver_id", user.getIdLong(), pageSize, page);
@@ -53,23 +71,35 @@ private List getUserReceivedLogPage(User user, int pageSize,
/**
* Get the last log entries for reputation donated by the user.
*
- * @param user user
- * @return sorted list of entries. the most recent first.
+ * @param user the user
+ * @param pageSize the number of entries per page
+ * @param page the page number
+ * @return a list of ReputationLogEntry objects
*/
private List getUserDonatedLogPage(User user, int pageSize, int page) {
return getLog("donor_id", user.getIdLong(), pageSize, page);
}
/**
- * Get the log entried for a message
+ * Get the log entries for a message.
*
- * @param messageId message id
- * @return sorted list of entries. the most recent first.
+ * @param messageId the message id
+ * @param count the number of entries to retrieve
+ * @return a list of ReputationLogEntry objects
*/
public List messageLog(long messageId, int count) {
return getLog("message_id", messageId, count, 0);
}
+ /**
+ * Get the log entries based on the specified column and id.
+ *
+ * @param column the column name to filter by
+ * @param id the id to filter by
+ * @param pageSize the number of entries per page
+ * @param page the page number
+ * @return a list of ReputationLogEntry objects
+ */
private List getLog(String column, long id, int pageSize, int page) {
return query("""
SELECT
@@ -95,6 +125,11 @@ private List getLog(String column, long id, int pageSize, in
.all();
}
+ /**
+ * Get the latest reputation log entry.
+ *
+ * @return an Optional containing the latest ReputationLogEntry if found
+ */
public Optional getLatestReputation() {
return query("""
SELECT
@@ -118,8 +153,8 @@ public Optional getLatestReputation() {
/**
* Get the first log entry for a message.
*
- * @param message message id
- * @return a log entry if found
+ * @param message the message id
+ * @return an Optional containing the ReputationLogEntry if found
*/
public Optional getLogEntry(long message) {
return query("""
@@ -144,23 +179,45 @@ public Optional getLogEntry(long message) {
}
/**
- * Get the log entries for a message.
+ * Get the log entry for a message.
*
- * @param message message
- * @return a log entry if found
+ * @param message the message
+ * @return an Optional containing the ReputationLogEntry if found
*/
public Optional getLogEntry(Message message) {
return getLogEntry(message.getIdLong());
}
+ /**
+ * Get the number of pages for the log entries donated by the user.
+ *
+ * @param user the user
+ * @param pageSize the number of entries per page
+ * @return the number of pages
+ */
private int getUserDonatedLogPages(User user, int pageSize) {
return getLogPages("donor_id", user.getIdLong(), pageSize);
}
+ /**
+ * Get the number of pages for the log entries received by the user.
+ *
+ * @param user the user
+ * @param pageSize the number of entries per page
+ * @return the number of pages
+ */
private int getUserReceivedLogPages(User user, int pageSize) {
return getLogPages("receiver_id", user.getIdLong(), pageSize);
}
+ /**
+ * Get the number of pages for the log entries based on the specified column and id.
+ *
+ * @param column the column name to filter by
+ * @param id the id to filter by
+ * @param pageSize the number of entries per page
+ * @return the number of pages
+ */
private int getLogPages(String column, long id, int pageSize) {
return query("""
SELECT
@@ -176,11 +233,21 @@ private int getLogPages(String column, long id, int pageSize) {
.orElse(1);
}
+ /**
+ * Returns the guild associated with this log.
+ *
+ * @return the guild
+ */
@Override
public Guild guild() {
return reputation.guild();
}
+ /**
+ * Returns the guild id associated with this log.
+ *
+ * @return the guild id
+ */
@Override
public long guildId() {
return reputation.guildId();
diff --git a/src/main/java/de/chojo/repbot/dao/access/guild/reputation/sub/Ranking.java b/src/main/java/de/chojo/repbot/dao/access/guild/reputation/sub/Ranking.java
index 6b582350c..a77d763cd 100644
--- a/src/main/java/de/chojo/repbot/dao/access/guild/reputation/sub/Ranking.java
+++ b/src/main/java/de/chojo/repbot/dao/access/guild/reputation/sub/Ranking.java
@@ -17,33 +17,78 @@
import static de.chojo.sadu.queries.api.call.Call.call;
import static de.chojo.sadu.queries.api.query.Query.query;
+/**
+ * Manages the ranking of users based on their reputation in a guild.
+ */
public class Ranking implements GuildHolder {
private final Reputation reputation;
+ /**
+ * Constructs a Ranking instance with the specified Reputation instance.
+ *
+ * @param reputation the Reputation instance
+ */
public Ranking(Reputation reputation) {
this.reputation = reputation;
}
+ /**
+ * Gets the total number of ranking pages.
+ *
+ * @param pageSize the size of a page
+ * @return the total number of ranking pages
+ */
private int getRankingPageCount(int pageSize) {
return pages(pageSize, "user_reputation");
}
+ /**
+ * Gets the total number of 7-day ranking pages.
+ *
+ * @param pageSize the size of a page
+ * @return the total number of 7-day ranking pages
+ */
private Integer get7DaysRankingPageCount(int pageSize) {
return pages(pageSize, "user_reputation_7_days");
}
+ /**
+ * Gets the total number of 30-day ranking pages.
+ *
+ * @param pageSize the size of a page
+ * @return the total number of 30-day ranking pages
+ */
private Integer get30DaysRankingPageCount(int pageSize) {
return pages(pageSize, "user_reputation_30_days");
}
+ /**
+ * Gets the total number of weekly ranking pages.
+ *
+ * @param pageSize the size of a page
+ * @return the total number of weekly ranking pages
+ */
private Integer getWeekRankingPageCount(int pageSize) {
return pages(pageSize, "user_reputation_week");
}
+ /**
+ * Gets the total number of monthly ranking pages.
+ *
+ * @param pageSize the size of a page
+ * @return the total number of monthly ranking pages
+ */
private Integer getMonthRankingPageCount(int pageSize) {
return pages(pageSize, "user_reputation_month");
}
+ /**
+ * Calculates the number of pages for a given table.
+ *
+ * @param pageSize the size of a page
+ * @param table the table name
+ * @return the number of pages
+ */
private Integer pages(int pageSize, String table) {
return query("""
SELECT
@@ -59,10 +104,23 @@ private Integer pages(int pageSize, String table) {
.orElse(1);
}
+ /**
+ * Gets the default ranking of the guild based on the reputation mode.
+ *
+ * @param pageSize the size of a page
+ * @return the default ranking of the guild
+ */
public GuildRanking defaultRanking(int pageSize) {
return byMode(reputation.repGuild().settings().general().reputationMode(), pageSize);
}
+ /**
+ * Gets the ranking of the guild based on the specified reputation mode.
+ *
+ * @param mode the reputation mode
+ * @param pageSize the size of a page
+ * @return the ranking of the guild
+ */
public GuildRanking byMode(ReputationMode mode, int pageSize) {
return switch (mode) {
case TOTAL -> total(pageSize);
@@ -70,12 +128,12 @@ public GuildRanking byMode(ReputationMode mode, int pageSize) {
case ROLLING_MONTH -> days30(pageSize);
case WEEK -> week(pageSize);
case MONTH -> month(pageSize);
- default -> throw new IllegalArgumentException("Unkown input " + mode);
+ default -> throw new IllegalArgumentException("Unknown input " + mode);
};
}
/**
- * Get the ranking of the guild.
+ * Gets the total ranking of the guild.
*
* @param pageSize the size of a page
* @return a sorted list of reputation users
@@ -85,7 +143,7 @@ public GuildRanking total(int pageSize) {
}
/**
- * Get the 7 days ranking of the guild.
+ * Gets the 7-day ranking of the guild.
*
* @param pageSize the size of a page
* @return a sorted list of reputation users
@@ -95,7 +153,7 @@ public GuildRanking days7(int pageSize) {
}
/**
- * Get the 30 days ranking of the guild.
+ * Gets the 30-day ranking of the guild.
*
* @param pageSize the size of a page
* @return a sorted list of reputation users
@@ -105,7 +163,7 @@ public GuildRanking days30(int pageSize) {
}
/**
- * Get the weekly ranking of the guild.
+ * Gets the weekly ranking of the guild.
*
* @param pageSize the size of a page
* @return a sorted list of reputation users
@@ -115,7 +173,7 @@ public GuildRanking week(int pageSize) {
}
/**
- * Get the monthly ranking of the guild.
+ * Gets the monthly ranking of the guild.
*
* @param pageSize the size of a page
* @return a sorted list of reputation users
@@ -125,32 +183,68 @@ public GuildRanking month(int pageSize) {
}
/**
- * Get the ranking of the guild.
+ * Gets the ranking of the guild.
*
* @param pageSize the size of a page
- * @param page the number of the page. zero based
+ * @param page the number of the page (zero-based)
* @return a sorted list of reputation users
*/
private List getRankingPage(int pageSize, int page) {
return getRankingPage(pageSize, page, "user_reputation");
}
+ /**
+ * Gets the 7-day ranking page of the guild.
+ *
+ * @param pageSize the size of a page
+ * @param page the number of the page (zero-based)
+ * @return a sorted list of reputation users
+ */
private List get7DaysRankingPage(int pageSize, int page) {
return getRankingPage(pageSize, page, "user_reputation_7_days");
}
+ /**
+ * Gets the 30-day ranking page of the guild.
+ *
+ * @param pageSize the size of a page
+ * @param page the number of the page (zero-based)
+ * @return a sorted list of reputation users
+ */
private List get30DaysRankingPage(int pageSize, int page) {
return getRankingPage(pageSize, page, "user_reputation_30_days");
}
+ /**
+ * Gets the weekly ranking page of the guild.
+ *
+ * @param pageSize the size of a page
+ * @param page the number of the page (zero-based)
+ * @return a sorted list of reputation users
+ */
private List getWeekRankingPage(int pageSize, int page) {
return getRankingPage(pageSize, page, "user_reputation_week");
}
+ /**
+ * Gets the monthly ranking page of the guild.
+ *
+ * @param pageSize the size of a page
+ * @param page the number of the page (zero-based)
+ * @return a sorted list of reputation users
+ */
private List getMonthRankingPage(int pageSize, int page) {
return getRankingPage(pageSize, page, "user_reputation_month");
}
+ /**
+ * Gets the ranking page of the guild for the specified table.
+ *
+ * @param pageSize the size of a page
+ * @param page the number of the page (zero-based)
+ * @param table the table name
+ * @return a sorted list of reputation users
+ */
private List getRankingPage(int pageSize, int page, String table) {
return query("""
SELECT
@@ -170,11 +264,21 @@ private List getRankingPage(int pageSize, int page, String table) {
.all();
}
+ /**
+ * Retrieves the guild associated with this instance.
+ *
+ * @return the guild
+ */
@Override
public Guild guild() {
return reputation.guild();
}
+ /**
+ * Retrieves the guild ID associated with this instance.
+ *
+ * @return the guild ID
+ */
@Override
public long guildId() {
return reputation.guildId();
diff --git a/src/main/java/de/chojo/repbot/dao/access/guild/reputation/sub/RepUser.java b/src/main/java/de/chojo/repbot/dao/access/guild/reputation/sub/RepUser.java
index 418176670..cd625a1ce 100644
--- a/src/main/java/de/chojo/repbot/dao/access/guild/reputation/sub/RepUser.java
+++ b/src/main/java/de/chojo/repbot/dao/access/guild/reputation/sub/RepUser.java
@@ -9,7 +9,6 @@
import de.chojo.repbot.config.Configuration;
import de.chojo.repbot.dao.access.guild.reputation.Reputation;
import de.chojo.repbot.dao.access.guild.reputation.sub.user.Gdpr;
-import de.chojo.repbot.dao.access.guild.settings.sub.AbuseProtection;
import de.chojo.repbot.dao.components.MemberHolder;
import de.chojo.repbot.dao.snapshots.RepProfile;
import net.dv8tion.jda.api.entities.Guild;
@@ -30,6 +29,9 @@
import static de.chojo.sadu.queries.api.query.Query.query;
import static org.slf4j.LoggerFactory.getLogger;
+/**
+ * Represents a user with reputation in a guild.
+ */
public class RepUser implements MemberHolder {
private static final Logger log = getLogger(RepUser.class);
private final Reputation reputation;
@@ -37,6 +39,12 @@ public class RepUser implements MemberHolder {
private final User user;
private Member member;
+ /**
+ * Constructs a RepUser with the specified reputation and member.
+ *
+ * @param reputation the reputation
+ * @param member the member
+ */
public RepUser(Reputation reputation, Member member) {
gdpr = new Gdpr(this);
this.reputation = reputation;
@@ -44,21 +52,32 @@ public RepUser(Reputation reputation, Member member) {
user = member.getUser();
}
+ /**
+ * Constructs a RepUser with the specified reputation and user.
+ *
+ * @param reputation the reputation
+ * @param user the user
+ */
public RepUser(Reputation reputation, User user) {
gdpr = new Gdpr(this);
this.reputation = reputation;
this.user = user;
}
+ /**
+ * Returns the GDPR settings for the user.
+ *
+ * @return the GDPR settings
+ */
public Gdpr gdpr() {
return gdpr;
}
/**
- * Add an amount of reputation to the reputation count of the user
+ * Adds an amount of reputation to the user's reputation count.
*
- * @param amount amount to add. Can be negative to subtract.
- * @return true if added
+ * @param amount the amount to add, can be negative to subtract
+ * @return true if the reputation was added
*/
public boolean addReputation(long amount) {
return query("""
@@ -70,20 +89,20 @@ INSERT INTO reputation_offset(guild_id, user_id, amount) VALUES (?,?,?)
}
/**
- * Removes an amount of reputation from the reputation count of the user.
+ * Removes an amount of reputation from the user's reputation count.
*
- * @param amount amount to remove
- * @return true if changed
+ * @param amount the amount to remove
+ * @return true if the reputation was removed
*/
public boolean removeReputation(long amount) {
return addReputation(-amount);
}
/**
- * Set the reputation offset to a value which will let the reputation of the user result in the entered amount.
+ * Sets the reputation offset to a value which will result in the specified reputation amount for the user.
*
* @param amount the reputation amount the user should have
- * @return true if changed.
+ * @return true if the reputation was set
*/
public boolean setReputation(long amount) {
var offset = amount - profile().reputation();
@@ -96,13 +115,13 @@ INSERT INTO reputation_offset(guild_id, user_id, amount) VALUES (?,?,?)
}
/**
- * Log reputation for a user.
+ * Logs reputation for a user.
*
- * @param donor donator of the reputation
- * @param message message to log
- * @param refMessage reference message if available
- * @param type type of reputation
- * @return true if the repuation was logged.
+ * @param donor the donor of the reputation
+ * @param message the message to log
+ * @param refMessage the reference message if available
+ * @param type the type of reputation
+ * @return true if the reputation was logged
*/
public boolean addReputation(@Nullable Member donor, @NotNull Message message, @Nullable Message refMessage, ThankType type) {
var success = query("""
@@ -119,21 +138,19 @@ ON CONFLICT(guild_id, donor_id, receiver_id, message_id)
.insert()
.changed();
if (success) {
- log.debug("{} received one reputation from {} on guild {} for message {}", userId(), donor != null ? donor.getIdLong() : "unkown", guildId(), message.getIdLong());
+ log.debug("{} received one reputation from {} on guild {} for message {}", userId(), donor != null ? donor.getIdLong() : "unknown", guildId(), message.getIdLong());
}
return success;
}
/**
- * Log reputation for a user.
- *
- * The received date will be dated back to {@link Message#getTimeCreated()}.
+ * Logs reputation for a user with a backdated received date.
*
- * @param donor donator of the reputation
- * @param message message to log
- * @param refMessage reference message if available
- * @param type type of reputation
- * @return true if the repuation was logged.
+ * @param donor the donor of the reputation
+ * @param message the message to log
+ * @param refMessage the reference message if available
+ * @param type the type of reputation
+ * @return true if the reputation was logged
*/
public boolean addOldReputation(@Nullable Member donor, @NotNull Message message, @Nullable Message refMessage, ThankType type) {
var success = query("""
@@ -153,17 +170,16 @@ ON CONFLICT(guild_id, donor_id, receiver_id, message_id)
.insert()
.changed();
if (success) {
- log.debug("{} received one reputation from {} for message {}", user().getName(), donor != null ? donor.getEffectiveName() : "unkown", message.getIdLong());
+ log.debug("{} received one reputation from {} for message {}", user().getName(), donor != null ? donor.getEffectiveName() : "unknown", message.getIdLong());
}
return success;
}
-
/**
- * Get the last time the user gave reputation to the user or received reputation from this user
+ * Gets the last time the user gave or received reputation from another user.
*
* @param other the other user
- * @return last timestamp as instant
+ * @return the last timestamp as an instant
*/
public Optional getLastReputation(Member other) {
return
@@ -189,10 +205,10 @@ public Optional getLastReputation(Member other) {
}
/**
- * Get the time since the last reputation.
+ * Gets the time since the last reputation interaction with another user.
*
- * @param other receiver
- * @return the time since the last vote in the requested time unit or 1 year if no entry was found.
+ * @param other the other user
+ * @return the duration since the last interaction or 1 year if no entry was found
*/
public Duration getLastRatedDuration(Member other) {
return getLastReputation(other).map(last -> Duration.between(last, Instant.now()))
@@ -200,9 +216,9 @@ public Duration getLastRatedDuration(Member other) {
}
/**
- * Get the reputation user.
+ * Gets the reputation profile of the user.
*
- * @return the reputation user
+ * @return the reputation profile
*/
public RepProfile profile() {
var mode = reputation.repGuild().settings().general().reputationMode();
@@ -232,9 +248,9 @@ public RepProfile profile() {
}
/**
- * Get the amount of received reputation based on {@link AbuseProtection#maxReceivedHours()}
+ * Gets the amount of received reputation based on the maximum received hours.
*
- * @return amount of received reputation
+ * @return the amount of received reputation
*/
public int countReceived() {
var hours = reputation().repGuild().settings().abuseProtection().maxReceivedHours();
@@ -246,9 +262,9 @@ public int countReceived() {
}
/**
- * Get the amount of received reputation based on {@link AbuseProtection#maxGivenHours()}
+ * Gets the amount of given reputation based on the maximum given hours.
*
- * @return amount of given reputation
+ * @return the amount of given reputation
*/
public int countGiven() {
var hours = reputation().repGuild().settings().abuseProtection().maxGivenHours();
@@ -259,30 +275,61 @@ public int countGiven() {
.orElse(0);
}
+ /**
+ * Returns the member associated with this RepUser.
+ *
+ * @return the member
+ */
@Override
public Member member() {
return member;
}
+ /**
+ * Returns the user associated with this RepUser.
+ *
+ * @return the user
+ */
@Override
public User user() {
return user;
}
+ /**
+ * Returns the guild associated with this RepUser.
+ *
+ * @return the guild
+ */
@Override
public Guild guild() {
return reputation.guild();
}
+ /**
+ * Refreshes the member associated with this RepUser.
+ *
+ * @param member the member
+ * @return the refreshed RepUser
+ */
public RepUser refresh(Member member) {
this.member = member;
return this;
}
+ /**
+ * Returns the reputation associated with this RepUser.
+ *
+ * @return the reputation
+ */
public Reputation reputation() {
return reputation;
}
+ /**
+ * Returns the configuration associated with this RepUser.
+ *
+ * @return the configuration
+ */
public Configuration configuration() {
return reputation.configuration();
}
diff --git a/src/main/java/de/chojo/repbot/dao/access/guild/reputation/sub/user/Gdpr.java b/src/main/java/de/chojo/repbot/dao/access/guild/reputation/sub/user/Gdpr.java
index 77f62660b..913f0d44d 100644
--- a/src/main/java/de/chojo/repbot/dao/access/guild/reputation/sub/user/Gdpr.java
+++ b/src/main/java/de/chojo/repbot/dao/access/guild/reputation/sub/user/Gdpr.java
@@ -16,19 +16,35 @@
import static de.chojo.sadu.queries.api.query.Query.query;
import static org.slf4j.LoggerFactory.getLogger;
+/**
+ * Provides GDPR-related data access methods for users.
+ */
public class Gdpr implements MemberHolder {
private final RepUser repUser;
private static final Logger log = getLogger(Gdpr.class);
+ /**
+ * Constructs a new Gdpr instance.
+ *
+ * @param repUser the RepUser instance
+ */
public Gdpr(RepUser repUser) {
this.repUser = repUser;
}
+ /**
+ * Retrieves the member associated with this instance.
+ *
+ * @return the member
+ */
@Override
public Member member() {
return repUser.member();
}
+ /**
+ * Queues the user for deletion by adding them to the cleanup schedule.
+ */
public void queueDeletion() {
log.info("User {} is scheduled for deletion on guild {}", userId(), guildId());
query("""
@@ -44,6 +60,9 @@ ON CONFLICT(guild_id, user_id)
.update();
}
+ /**
+ * Dequeues the user from deletion by removing them from the cleanup schedule.
+ */
public void dequeueDeletion() {
if (query("""
DELETE FROM
@@ -58,11 +77,21 @@ public void dequeueDeletion() {
}
}
+ /**
+ * Retrieves the user associated with this instance.
+ *
+ * @return the user
+ */
@Override
public User user() {
return repUser.user();
}
+ /**
+ * Retrieves the guild associated with this instance.
+ *
+ * @return the guild
+ */
@Override
public Guild guild() {
return repUser.guild();
diff --git a/src/main/java/de/chojo/repbot/dao/access/guild/settings/sub/AbuseProtection.java b/src/main/java/de/chojo/repbot/dao/access/guild/settings/sub/AbuseProtection.java
index 26cb0731c..df94e285b 100644
--- a/src/main/java/de/chojo/repbot/dao/access/guild/settings/sub/AbuseProtection.java
+++ b/src/main/java/de/chojo/repbot/dao/access/guild/settings/sub/AbuseProtection.java
@@ -21,6 +21,9 @@
import static de.chojo.sadu.queries.api.call.Call.call;
import static de.chojo.sadu.queries.api.query.Query.query;
+/**
+ * Handles abuse protection settings for a guild.
+ */
public class AbuseProtection implements GuildHolder {
private final Settings settings;
private int cooldown;
@@ -34,6 +37,21 @@ public class AbuseProtection implements GuildHolder {
private int maxReceivedHours;
private int maxMessageReputation;
+ /**
+ * Constructs an AbuseProtection object with specified settings.
+ *
+ * @param settings the settings
+ * @param cooldown the cooldown period
+ * @param maxMessageAge the maximum age of messages
+ * @param minMessages the minimum number of messages
+ * @param donorContext whether donor context is enabled
+ * @param receiverContext whether receiver context is enabled
+ * @param maxGiven the maximum given reputation
+ * @param maxGivenHours the hours for max given reputation
+ * @param maxReceived the maximum received reputation
+ * @param maxReceivedHours the hours for max received reputation
+ * @param maxMessageReputation the maximum reputation per message
+ */
public AbuseProtection(Settings settings, int cooldown, int maxMessageAge, int minMessages, boolean donorContext, boolean receiverContext,
int maxGiven, int maxGivenHours, int maxReceived, int maxReceivedHours, int maxMessageReputation) {
this.settings = settings;
@@ -49,10 +67,23 @@ public AbuseProtection(Settings settings, int cooldown, int maxMessageAge, int m
this.maxMessageReputation = maxMessageReputation;
}
+ /**
+ * Constructs an AbuseProtection object with default settings.
+ *
+ * @param settings the settings
+ */
public AbuseProtection(Settings settings) {
this(settings, 30, 30, 10, true, true, 0, 1, 0, 1, 3);
}
+ /**
+ * Builds an AbuseProtection object from the database row.
+ *
+ * @param settings the settings
+ * @param rs the database row
+ * @return the AbuseProtection object
+ * @throws SQLException if a database access error occurs
+ */
public static AbuseProtection build(Settings settings, Row rs) throws SQLException {
return new AbuseProtection(settings,
rs.getInt("cooldown"),
@@ -67,46 +98,102 @@ public static AbuseProtection build(Settings settings, Row rs) throws SQLExcepti
rs.getInt("max_message_reputation"));
}
+ /**
+ * Gets the cooldown period.
+ *
+ * @return the cooldown period
+ */
public int cooldown() {
return cooldown;
}
+ /**
+ * Gets the maximum age of messages.
+ *
+ * @return the maximum age of messages
+ */
public int maxMessageAge() {
return maxMessageAge;
}
+ /**
+ * Gets the minimum number of messages.
+ *
+ * @return the minimum number of messages
+ */
public int minMessages() {
return minMessages;
}
+ /**
+ * Gets the maximum reputation per message.
+ *
+ * @return the maximum reputation per message
+ */
public int maxMessageReputation() {
return maxMessageReputation;
}
+ /**
+ * Checks if donor context is enabled.
+ *
+ * @return true if donor context is enabled, false otherwise
+ */
public boolean isDonorContext() {
return donorContext;
}
+ /**
+ * Checks if receiver context is enabled.
+ *
+ * @return true if receiver context is enabled, false otherwise
+ */
public boolean isReceiverContext() {
return receiverContext;
}
+ /**
+ * Gets the maximum given reputation.
+ *
+ * @return the maximum given reputation
+ */
public int maxGiven() {
return maxGiven;
}
+ /**
+ * Gets the hours for max given reputation.
+ *
+ * @return the hours for max given reputation
+ */
public int maxGivenHours() {
return maxGivenHours;
}
+ /**
+ * Gets the maximum received reputation.
+ *
+ * @return the maximum received reputation
+ */
public int maxReceived() {
return maxReceived;
}
+ /**
+ * Gets the hours for max received reputation.
+ *
+ * @return the hours for max received reputation
+ */
public int maxReceivedHours() {
return maxReceivedHours;
}
+ /**
+ * Sets the cooldown period.
+ *
+ * @param cooldown the cooldown period
+ * @return the updated cooldown period
+ */
public int cooldown(int cooldown) {
if (set("cooldown", stmt -> stmt.bind(cooldown))) {
this.cooldown = cooldown;
@@ -114,6 +201,12 @@ public int cooldown(int cooldown) {
return this.cooldown;
}
+ /**
+ * Sets the maximum age of messages.
+ *
+ * @param maxMessageAge the maximum age of messages
+ * @return the updated maximum age of messages
+ */
public int maxMessageAge(int maxMessageAge) {
if (set("max_message_age", stmt -> stmt.bind(maxMessageAge))) {
this.maxMessageAge = maxMessageAge;
@@ -121,6 +214,12 @@ public int maxMessageAge(int maxMessageAge) {
return this.maxMessageAge;
}
+ /**
+ * Sets the minimum number of messages.
+ *
+ * @param minMessages the minimum number of messages
+ * @return the updated minimum number of messages
+ */
public int minMessages(int minMessages) {
if (set("min_messages", stmt -> stmt.bind(minMessages))) {
this.minMessages = minMessages;
@@ -128,6 +227,12 @@ public int minMessages(int minMessages) {
return this.minMessages;
}
+ /**
+ * Sets whether donor context is enabled.
+ *
+ * @param donorContext the donor context status
+ * @return the updated donor context status
+ */
public boolean donorContext(boolean donorContext) {
if (set("donor_context", stmt -> stmt.bind(donorContext))) {
this.donorContext = donorContext;
@@ -135,6 +240,12 @@ public boolean donorContext(boolean donorContext) {
return this.donorContext;
}
+ /**
+ * Sets whether receiver context is enabled.
+ *
+ * @param receiverContext the receiver context status
+ * @return the updated receiver context status
+ */
public boolean receiverContext(boolean receiverContext) {
if (set("receiver_context", stmt -> stmt.bind(receiverContext))) {
this.receiverContext = receiverContext;
@@ -142,6 +253,12 @@ public boolean receiverContext(boolean receiverContext) {
return this.receiverContext;
}
+ /**
+ * Sets the maximum given reputation.
+ *
+ * @param maxGiven the maximum given reputation
+ * @return the updated maximum given reputation
+ */
public int maxGiven(int maxGiven) {
var result = set("max_given", stmt -> stmt.bind(Math.max(maxGiven, 0)));
if (result) {
@@ -150,6 +267,12 @@ public int maxGiven(int maxGiven) {
return this.maxGiven;
}
+ /**
+ * Sets the hours for max given reputation.
+ *
+ * @param maxGivenHours the hours for max given reputation
+ * @return the updated hours for max given reputation
+ */
public int maxGivenHours(int maxGivenHours) {
var result = set("max_given_hours", stmt -> stmt.bind(Math.max(maxGivenHours, 1)));
if (result) {
@@ -158,6 +281,12 @@ public int maxGivenHours(int maxGivenHours) {
return this.maxGivenHours;
}
+ /**
+ * Sets the maximum received reputation.
+ *
+ * @param maxReceived the maximum received reputation
+ * @return the updated maximum received reputation
+ */
public int maxReceived(int maxReceived) {
var result = set("max_received", stmt -> stmt.bind(Math.max(maxReceived, 0)));
if (result) {
@@ -166,6 +295,12 @@ public int maxReceived(int maxReceived) {
return this.maxReceived;
}
+ /**
+ * Sets the hours for max received reputation.
+ *
+ * @param maxReceivedHours the hours for max received reputation
+ * @return the updated hours for max received reputation
+ */
public int maxReceivedHours(int maxReceivedHours) {
var result = set("max_received_hours", stmt -> stmt.bind(Math.max(maxReceivedHours, 1)));
if (result) {
@@ -174,6 +309,12 @@ public int maxReceivedHours(int maxReceivedHours) {
return this.maxReceivedHours;
}
+ /**
+ * Sets the maximum reputation per message.
+ *
+ * @param maxMessageReputation the maximum reputation per message
+ * @return the updated maximum reputation per message
+ */
public int maxMessageReputation(int maxMessageReputation) {
if (set("max_message_reputation", stmt -> stmt.bind(maxMessageReputation))) {
this.maxMessageReputation = maxMessageReputation;
@@ -181,6 +322,12 @@ public int maxMessageReputation(int maxMessageReputation) {
return this.maxMessageReputation;
}
+ /**
+ * Checks if a message is older than the maximum message age.
+ *
+ * @param message the message to check
+ * @return true if the message is older than the maximum message age, false otherwise
+ */
public boolean isOldMessage(Message message) {
if (maxMessageAge == 0) return false;
var until = message.getTimeCreated().toInstant().until(Instant.now(), ChronoUnit.MINUTES);
@@ -188,7 +335,7 @@ public boolean isOldMessage(Message message) {
}
/**
- * Checks if the member has reached the {@link #maxGiven} amount of reputation in the last {@link #maxGivenHours}.
+ * Checks if the member has reached the max given reputation in the last max given hours.
*
* @param member member to check
* @return true if the limit is reached
@@ -199,7 +346,7 @@ public boolean isDonorLimit(Member member) {
}
/**
- * Checks if the member has reached the {@link #maxReceived} amount of reputation in the last {@link #maxReceivedHours}.
+ * Checks if the member has reached the max received reputation in the last max received hours.
*
* @param member member to check
* @return true if the limit is reached
@@ -209,14 +356,31 @@ public boolean isReceiverLimit(Member member) {
return settings.repGuild().reputation().user(member).countReceived() >= maxReceived;
}
+ /**
+ * Checks if the donor limit is enabled.
+ *
+ * @return true if the donor limit is enabled, false otherwise
+ */
public boolean isDonorLimit() {
return maxGiven != 0;
}
+ /**
+ * Checks if the receiver limit is enabled.
+ *
+ * @return true if the receiver limit is enabled, false otherwise
+ */
public boolean isReceiverLimit() {
return maxReceived != 0;
}
+ /**
+ * Sets a parameter in the database.
+ *
+ * @param parameter the parameter to set
+ * @param builder the function to build the call
+ * @return true if the parameter was set successfully, false otherwise
+ */
private boolean set(String parameter, Function builder) {
return query("""
INSERT INTO abuse_protection(guild_id, %s) VALUES (?, ?)
@@ -228,28 +392,43 @@ ON CONFLICT(guild_id)
.changed();
}
+ /**
+ * Gets the guild associated with the settings.
+ *
+ * @return the guild
+ */
@Override
public Guild guild() {
return settings.guild();
}
+ /**
+ * Gets the ID of the guild associated with the settings.
+ *
+ * @return the guild ID
+ */
@Override
public long guildId() {
return settings.guildId();
}
+ /**
+ * Returns a pretty string representation of the abuse protection settings.
+ *
+ * @return the pretty string
+ */
public String prettyString() {
return """
**Context**
Donor: %s
Receiver: %s
-
+
**Limits**
Given: %s in %s hours
Received: %s in %s hours
Per Message: %s
Cooldown: %s
-
+
**Age**
Max Age: %s minutes
Min Messages: %s
diff --git a/src/main/java/de/chojo/repbot/dao/access/guild/settings/sub/Announcements.java b/src/main/java/de/chojo/repbot/dao/access/guild/settings/sub/Announcements.java
index 58d90e98e..393f115f0 100644
--- a/src/main/java/de/chojo/repbot/dao/access/guild/settings/sub/Announcements.java
+++ b/src/main/java/de/chojo/repbot/dao/access/guild/settings/sub/Announcements.java
@@ -18,12 +18,23 @@
import static de.chojo.sadu.queries.api.call.Call.call;
import static de.chojo.sadu.queries.api.query.Query.query;
+/**
+ * Handles announcements settings for a guild.
+ */
public class Announcements implements GuildHolder {
private final Settings settings;
private boolean active = false;
private boolean sameChannel = true;
private long channelId = 0;
+ /**
+ * Constructs an Announcements object with specified settings.
+ *
+ * @param settings the settings
+ * @param active whether the announcements are active
+ * @param sameChannel whether the announcements should be sent to the same channel
+ * @param channelId the ID of the channel for announcements
+ */
private Announcements(Settings settings, boolean active, boolean sameChannel, long channelId) {
this.settings = settings;
this.active = active;
@@ -31,10 +42,23 @@ private Announcements(Settings settings, boolean active, boolean sameChannel, lo
this.channelId = channelId;
}
+ /**
+ * Constructs an Announcements object with specified settings.
+ *
+ * @param settings the settings
+ */
public Announcements(Settings settings) {
this.settings = settings;
}
+ /**
+ * Builds an Announcements object from the database row.
+ *
+ * @param settings the settings
+ * @param rs the database row
+ * @return the Announcements object
+ * @throws SQLException if a database access error occurs
+ */
public static Announcements build(Settings settings, Row rs) throws SQLException {
return new Announcements(settings,
rs.getBoolean("active"),
@@ -42,18 +66,39 @@ public static Announcements build(Settings settings, Row rs) throws SQLException
rs.getLong("channel_id"));
}
+ /**
+ * Checks if the announcements are active.
+ *
+ * @return true if active, false otherwise
+ */
public boolean isActive() {
return active;
}
+ /**
+ * Checks if the announcements should be sent to the same channel.
+ *
+ * @return true if same channel, false otherwise
+ */
public boolean isSameChannel() {
return sameChannel;
}
+ /**
+ * Gets the ID of the channel for announcements.
+ *
+ * @return the channel ID
+ */
public long channelId() {
return channelId;
}
+ /**
+ * Sets the active status of the announcements.
+ *
+ * @param active the active status
+ * @return the updated active status
+ */
public boolean active(boolean active) {
if (set("active", stmt -> stmt.bind(active))) {
this.active = active;
@@ -61,6 +106,12 @@ public boolean active(boolean active) {
return this.active;
}
+ /**
+ * Sets whether the announcements should be sent to the same channel.
+ *
+ * @param sameChannel the same channel status
+ * @return the updated same channel status
+ */
public boolean sameChannel(boolean sameChannel) {
if (set("same_channel", stmt -> stmt.bind(sameChannel))) {
this.sameChannel = sameChannel;
@@ -68,6 +119,12 @@ public boolean sameChannel(boolean sameChannel) {
return this.sameChannel;
}
+ /**
+ * Sets the channel for announcements.
+ *
+ * @param textChannel the text channel
+ * @return the updated channel ID
+ */
public long channel(TextChannel textChannel) {
if (set("channel_id", stmt -> stmt.bind(textChannel.getIdLong()))) {
channelId = textChannel.getIdLong();
@@ -75,6 +132,13 @@ public long channel(TextChannel textChannel) {
return channelId;
}
+ /**
+ * Sets a parameter in the database.
+ *
+ * @param parameter the parameter to set
+ * @param builder the function to build the call
+ * @return true if the parameter was set successfully, false otherwise
+ */
private boolean set(String parameter, Function builder) {
return query("""
INSERT INTO announcements(guild_id, %s) VALUES (?, ?)
@@ -86,16 +150,31 @@ ON CONFLICT(guild_id)
.changed();
}
+ /**
+ * Gets the guild associated with the settings.
+ *
+ * @return the guild
+ */
@Override
public Guild guild() {
return settings.guild();
}
+ /**
+ * Gets the ID of the guild associated with the settings.
+ *
+ * @return the guild ID
+ */
@Override
public long guildId() {
return settings.guildId();
}
-
+
+ /**
+ * Returns a pretty string representation of the announcement settings.
+ *
+ * @return the pretty string
+ */
public String prettyString() {
return """
Active: %s
diff --git a/src/main/java/de/chojo/repbot/dao/access/guild/settings/sub/General.java b/src/main/java/de/chojo/repbot/dao/access/guild/settings/sub/General.java
index b09f2bed9..4d64e6b1b 100644
--- a/src/main/java/de/chojo/repbot/dao/access/guild/settings/sub/General.java
+++ b/src/main/java/de/chojo/repbot/dao/access/guild/settings/sub/General.java
@@ -23,6 +23,9 @@
import static de.chojo.sadu.queries.api.call.Call.call;
import static de.chojo.sadu.queries.api.query.Query.query;
+/**
+ * Represents the general settings for a guild.
+ */
public class General implements GuildHolder {
private final AtomicBoolean stackRoles;
private final Settings settings;
@@ -31,10 +34,25 @@ public class General implements GuildHolder {
private ReputationMode reputationMode;
private LocalDate resetDate;
+ /**
+ * Constructs a new General instance with default values.
+ *
+ * @param settings the Settings instance
+ */
public General(Settings settings) {
this(settings, null, true, false, ReputationMode.TOTAL, null);
}
+ /**
+ * Constructs a new General instance with specified values.
+ *
+ * @param settings the Settings instance
+ * @param language the DiscordLocale for the language
+ * @param emojiDebug whether emoji debug is enabled
+ * @param stackRoles whether stack roles is enabled
+ * @param reputationMode the ReputationMode
+ * @param resetDate the reset date
+ */
public General(Settings settings, DiscordLocale language, boolean emojiDebug, boolean stackRoles, ReputationMode reputationMode, LocalDate resetDate) {
this.settings = settings;
this.language = language;
@@ -44,6 +62,14 @@ public General(Settings settings, DiscordLocale language, boolean emojiDebug, bo
this.resetDate = resetDate;
}
+ /**
+ * Builds a General instance from the given database row.
+ *
+ * @param settings the Settings instance
+ * @param rs the database row
+ * @return the General instance
+ * @throws SQLException if a database access error occurs
+ */
public static General build(Settings settings, Row rs) throws SQLException {
var lang = rs.getString("language");
return new General(settings,
@@ -54,6 +80,12 @@ public static General build(Settings settings, Row rs) throws SQLException {
Optional.ofNullable(rs.getDate("reset_date")).map(Date::toLocalDate).orElse(null));
}
+ /**
+ * Sets the language for the guild.
+ *
+ * @param language the DiscordLocale for the language
+ * @return true if the language was successfully set, false otherwise
+ */
public boolean language(@Nullable DiscordLocale language) {
var result = set("language", stmt -> stmt.bind(language == null ? null : language.getLocale()));
if (result) {
@@ -62,6 +94,12 @@ public boolean language(@Nullable DiscordLocale language) {
return result;
}
+ /**
+ * Sets the emoji debug status for the guild.
+ *
+ * @param emojiDebug whether emoji debug is enabled
+ * @return true if the emoji debug status was successfully set, false otherwise
+ */
public boolean emojiDebug(boolean emojiDebug) {
var result = set("emoji_debug", stmt -> stmt.bind(emojiDebug));
if (result) {
@@ -70,6 +108,12 @@ public boolean emojiDebug(boolean emojiDebug) {
return result;
}
+ /**
+ * Sets the reputation mode for the guild.
+ *
+ * @param reputationMode the ReputationMode
+ * @return the ReputationMode that was set
+ */
public ReputationMode reputationMode(ReputationMode reputationMode) {
var result = set("reputation_mode", stmt -> stmt.bind(reputationMode.name()));
if (result) {
@@ -78,6 +122,12 @@ public ReputationMode reputationMode(ReputationMode reputationMode) {
return reputationMode;
}
+ /**
+ * Sets the stack roles status for the guild.
+ *
+ * @param stackRoles whether stack roles is enabled
+ * @return true if the stack roles status was successfully set, false otherwise
+ */
public boolean stackRoles(boolean stackRoles) {
var result = set("stack_roles", stmt -> stmt.bind(stackRoles));
if (result) {
@@ -86,6 +136,12 @@ public boolean stackRoles(boolean stackRoles) {
return result;
}
+ /**
+ * Sets the reset date for the guild.
+ *
+ * @param resetDate the reset date
+ * @return true if the reset date was successfully set, false otherwise
+ */
public boolean resetDate(LocalDate resetDate) {
var result = set("reset_date", stmt -> stmt.bind(resetDate == null ? null : Date.valueOf(resetDate)));
if (result) {
@@ -94,36 +150,78 @@ public boolean resetDate(LocalDate resetDate) {
return result;
}
+ /**
+ * Retrieves the language for the guild.
+ *
+ * @return an Optional containing the DiscordLocale for the language, or an empty Optional if not set
+ */
public Optional language() {
return Optional.ofNullable(language);
}
+ /**
+ * Checks if emoji debug is enabled for the guild.
+ *
+ * @return true if emoji debug is enabled, false otherwise
+ */
public boolean isEmojiDebug() {
return emojiDebug;
}
+ /**
+ * Checks if stack roles is enabled for the guild.
+ *
+ * @return true if stack roles is enabled, false otherwise
+ */
public boolean isStackRoles() {
return stackRoles.get();
}
+ /**
+ * Retrieves the AtomicBoolean representing the stack roles status for the guild.
+ *
+ * @return the AtomicBoolean representing the stack roles status
+ */
public AtomicBoolean stackRoles() {
return stackRoles;
}
+ /**
+ * Retrieves the reset date for the guild.
+ *
+ * @return the reset date
+ */
public LocalDate resetDate() {
return resetDate;
}
+ /**
+ * Retrieves the guild associated with this instance.
+ *
+ * @return the guild
+ */
@Override
public Guild guild() {
return settings.guild();
}
+ /**
+ * Retrieves the ID of the guild associated with this instance.
+ *
+ * @return the guild ID
+ */
@Override
public long guildId() {
return settings.guildId();
}
+ /**
+ * Sets a parameter in the database for the guild.
+ *
+ * @param parameter the parameter to set
+ * @param builder the function to build the Call
+ * @return true if the parameter was successfully set, false otherwise
+ */
private boolean set(String parameter, Function builder) {
return query("""
INSERT INTO guild_settings(guild_id, %s) VALUES (?, ?)
@@ -135,10 +233,20 @@ ON CONFLICT(guild_id)
.changed();
}
+ /**
+ * Retrieves the reputation mode for the guild.
+ *
+ * @return the ReputationMode
+ */
public ReputationMode reputationMode() {
return reputationMode;
}
+ /**
+ * Returns a pretty string representation of the general settings.
+ *
+ * @return a pretty string representation of the general settings
+ */
public String prettyString() {
return """
Stack roles: %s
diff --git a/src/main/java/de/chojo/repbot/dao/access/guild/settings/sub/Ranks.java b/src/main/java/de/chojo/repbot/dao/access/guild/settings/sub/Ranks.java
index 0ad78d90d..f8ef351ae 100644
--- a/src/main/java/de/chojo/repbot/dao/access/guild/settings/sub/Ranks.java
+++ b/src/main/java/de/chojo/repbot/dao/access/guild/settings/sub/Ranks.java
@@ -22,23 +22,32 @@
import static de.chojo.sadu.queries.api.call.Call.call;
import static de.chojo.sadu.queries.api.query.Query.query;
+/**
+ * Manages the reputation ranks for a guild.
+ */
public class Ranks implements GuildHolder {
private final LinkedHashSet ranks = new LinkedHashSet<>();
private final Settings settings;
private final AtomicBoolean stackRoles;
+ /**
+ * Constructs a Ranks instance.
+ *
+ * @param settings the settings for the guild
+ * @param stackRoles whether to stack roles
+ */
public Ranks(Settings settings, AtomicBoolean stackRoles) {
this.settings = settings;
this.stackRoles = stackRoles;
}
/**
- * Add a reputation rank.
+ * Adds a reputation rank.
*
- * If the role or the reputation amount is already in use it will be removed first.
+ * If the role or the reputation amount is already in use, it will be removed first.
*
- * @param role role
- * @param reputation required reputation of role
+ * @param role the role
+ * @param reputation the required reputation of the role
* @return true if the role was added or updated
*/
public boolean add(Role role, long reputation) {
@@ -71,6 +80,11 @@ ON CONFLICT(guild_id, role_id)
return deleteRank;
}
+ /**
+ * Retrieves the list of reputation ranks.
+ *
+ * @return the list of reputation ranks
+ */
public List ranks() {
if (!ranks.isEmpty()) {
return ranks.stream().sorted().toList();
@@ -98,8 +112,8 @@ public List ranks() {
*
* This will contain up to {@link #ranks()}.size() when {@link General#stackRoles()} is false.
*
- * @param user user to check
- * @return list of ranks
+ * @param user the user to check
+ * @return the list of ranks
*/
public List currentRanks(RepUser user) {
var profile = user.profile();
@@ -110,6 +124,12 @@ public List currentRanks(RepUser user) {
.toList();
}
+ /**
+ * Gets the current rank of the user.
+ *
+ * @param user the user to check
+ * @return an optional containing the current rank if found, otherwise empty
+ */
public Optional currentRank(RepUser user) {
var profile = user.profile();
return ranks().stream()
@@ -119,22 +139,44 @@ public Optional currentRank(RepUser user) {
.findFirst();
}
+ /**
+ * Gets the next rank of the user.
+ *
+ * @param user the user to check
+ * @return an optional containing the next rank if found, otherwise empty
+ */
public Optional nextRank(RepUser user) {
var profile = user.profile();
return ranks().stream().filter(rank -> rank.reputation() > profile.reputation())
.sorted(Comparator.reverseOrder()).limit(1).findFirst();
}
+ /**
+ * Retrieves the guild associated with this instance.
+ *
+ * @return the guild
+ */
@Override
public Guild guild() {
return settings.guild();
}
+ /**
+ * Retrieves the guild ID associated with this instance.
+ *
+ * @return the guild ID
+ */
@Override
public long guildId() {
return settings.guildId();
}
+ /**
+ * Gets the rank associated with the specified role.
+ *
+ * @param role the role
+ * @return an optional containing the rank if found, otherwise empty
+ */
public Optional rank(Role role) {
return query("SELECT reputation FROM guild_ranks WHERE guild_id = ? AND role_id = ?")
.single(call().bind(guildId()).bind(role.getIdLong()))
@@ -142,10 +184,18 @@ public Optional rank(Role role) {
.first();
}
+ /**
+ * Refreshes the ranks by clearing the current list.
+ */
public void refresh() {
ranks.clear();
}
+ /**
+ * Generates a pretty string representation of the ranks.
+ *
+ * @return a pretty string representation of the ranks
+ */
public String prettyString() {
return ranks().stream().filter(r -> r.role().isPresent())
.map(rank -> "%s(%d) %d".formatted(rank.role().get().getName(), rank.role().get().getPosition(), rank.reputation()))
diff --git a/src/main/java/de/chojo/repbot/dao/access/guild/settings/sub/thanking/Channels.java b/src/main/java/de/chojo/repbot/dao/access/guild/settings/sub/thanking/Channels.java
index dc9c778dc..421b84776 100644
--- a/src/main/java/de/chojo/repbot/dao/access/guild/settings/sub/thanking/Channels.java
+++ b/src/main/java/de/chojo/repbot/dao/access/guild/settings/sub/thanking/Channels.java
@@ -27,7 +27,10 @@
import static de.chojo.sadu.queries.api.query.Query.query;
import static org.slf4j.LoggerFactory.getLogger;
-public class Channels implements GuildHolder {
+/**
+ * Class representing the channels configuration for thanking settings.
+ */
+public class Channels implements GuildHolder {
private static final Logger log = getLogger(Channels.class);
@@ -36,6 +39,14 @@ public class Channels implements GuildHolder {
private final Set categories;
private boolean whitelist;
+ /**
+ * Constructs a Channels instance with the specified thanking settings, whitelist status, channels, and categories.
+ *
+ * @param thanking the thanking settings
+ * @param whitelist the whitelist status
+ * @param channels the set of channel IDs
+ * @param categories the set of category IDs
+ */
public Channels(Thanking thanking, boolean whitelist, Set channels, Set categories) {
this.thanking = thanking;
this.whitelist = whitelist;
@@ -53,6 +64,12 @@ public long guildId() {
return thanking.guildId();
}
+ /**
+ * Checks if the given channel is enabled for thanking.
+ *
+ * @param channel the guild message channel
+ * @return true if the channel is enabled, false otherwise
+ */
public boolean isEnabled(GuildMessageChannel channel) {
StandardGuildChannel baseChannel;
if (channel instanceof ThreadChannel bc) {
@@ -71,40 +88,72 @@ public boolean isEnabled(GuildMessageChannel channel) {
return isEnabledByChannel(baseChannel) || isEnabledByCategory(baseChannel.getParentCategory());
}
+ /**
+ * Checks if the given channel is enabled by channel ID.
+ *
+ * @param channel the standard guild channel
+ * @return true if the channel is enabled, false otherwise
+ */
public boolean isEnabledByChannel(StandardGuildChannel channel) {
return isWhitelist() == channels.contains(channel.getIdLong());
}
+ /**
+ * Checks if the given category is enabled by category ID.
+ *
+ * @param category the category
+ * @return true if the category is enabled, false otherwise
+ */
public boolean isEnabledByCategory(@Nullable Category category) {
if (category == null) return false;
return isWhitelist() == categories.contains(category.getIdLong());
}
+ /**
+ * Gets the list of enabled guild channels.
+ *
+ * @return the list of enabled guild channels
+ */
public List channels() {
return channels.stream().map(guild()::getGuildChannelById)
.filter(Objects::nonNull)
.toList();
}
+ /**
+ * Gets the list of enabled categories.
+ *
+ * @return the list of enabled categories
+ */
public List categories() {
return categories.stream().map(guild()::getCategoryById)
.filter(Objects::nonNull)
.toList();
}
+ /**
+ * Gets the set of channel IDs.
+ *
+ * @return the set of channel IDs
+ */
public Set channelIds() {
return channels;
}
+ /**
+ * Checks if the whitelist is enabled.
+ *
+ * @return true if the whitelist is enabled, false otherwise
+ */
public boolean isWhitelist() {
return whitelist;
}
/**
- * Add a channel to reputation channel
+ * Adds a channel to the reputation channels.
*
- * @param channel channel
- * @return true if a channel was added
+ * @param channel the standard guild channel
+ * @return true if the channel was added, false otherwise
*/
public boolean add(StandardGuildChannel channel) {
var result = query("INSERT INTO active_channel(guild_id, channel_id) VALUES(?,?) ON CONFLICT(guild_id, channel_id) DO NOTHING;")
@@ -118,10 +167,10 @@ public boolean add(StandardGuildChannel channel) {
}
/**
- * Add a category to reputation categories
+ * Adds a category to the reputation categories.
*
- * @param category category
- * @return true if a category was added
+ * @param category the category
+ * @return true if the category was added, false otherwise
*/
public boolean add(Category category) {
var result = query("INSERT INTO active_categories(guild_id, category_id) VALUES(?,?) ON CONFLICT(guild_id, category_id) DO NOTHING;")
@@ -135,10 +184,10 @@ public boolean add(Category category) {
}
/**
- * Remove a reputation channel
+ * Removes a reputation channel.
*
- * @param channel channel
- * @return true if the channel was removed
+ * @param channel the channel
+ * @return true if the channel was removed, false otherwise
*/
public boolean remove(Channel channel) {
var result = query("DELETE FROM active_channel WHERE guild_id = ? AND channel_id = ?;")
@@ -152,13 +201,13 @@ public boolean remove(Channel channel) {
}
/**
- * Remove a reputation category
+ * Removes a reputation category.
*
- * @param category category
- * @return true if the channel was removed
+ * @param category the category
+ * @return true if the category was removed, false otherwise
*/
public boolean remove(Category category) {
- var result =query("DELETE FROM active_categories WHERE guild_id = ? AND category_id = ?;")
+ var result = query("DELETE FROM active_categories WHERE guild_id = ? AND category_id = ?;")
.single(call().bind(guildId()).bind(category.getIdLong()))
.update()
.changed();
@@ -169,9 +218,9 @@ public boolean remove(Category category) {
}
/**
- * Remove all channel of a guild
+ * Removes all channels of a guild.
*
- * @return the amount of removed channel
+ * @return the number of removed channels
*/
public int clearChannel() {
var result = query("DELETE FROM active_channel WHERE guild_id = ?;")
@@ -185,9 +234,9 @@ public int clearChannel() {
}
/**
- * Remove all categories of a guild
+ * Removes all categories of a guild.
*
- * @return the amount of removed categories
+ * @return the number of removed categories
*/
public int clearCategories() {
var result = query("DELETE FROM active_categories WHERE guild_id = ?;")
@@ -200,6 +249,12 @@ public int clearCategories() {
return result;
}
+ /**
+ * Sets the list type to whitelist or blacklist.
+ *
+ * @param whitelist the whitelist status
+ * @return true if the whitelist status was updated, false otherwise
+ */
public boolean listType(boolean whitelist) {
var result = query("""
INSERT INTO thank_settings(guild_id, channel_whitelist) VALUES (?,?)
diff --git a/src/main/java/de/chojo/repbot/dao/access/guild/settings/sub/thanking/Reactions.java b/src/main/java/de/chojo/repbot/dao/access/guild/settings/sub/thanking/Reactions.java
index 7b86f5689..3125fd627 100644
--- a/src/main/java/de/chojo/repbot/dao/access/guild/settings/sub/thanking/Reactions.java
+++ b/src/main/java/de/chojo/repbot/dao/access/guild/settings/sub/thanking/Reactions.java
@@ -22,27 +22,53 @@
import static de.chojo.sadu.queries.api.call.Call.call;
import static de.chojo.sadu.queries.api.query.Query.query;
-public class Reactions implements GuildHolder {
+/**
+ * Manages the reactions for thanking in a guild.
+ */
+public class Reactions implements GuildHolder {
private final Thanking thanking;
private final Set reactions;
private String mainReaction;
+ /**
+ * Constructs a Reactions instance.
+ *
+ * @param thanking the thanking settings
+ * @param mainReaction the main reaction
+ * @param reactions the set of additional reactions
+ */
public Reactions(Thanking thanking, String mainReaction, Set reactions) {
this.thanking = thanking;
this.mainReaction = mainReaction;
this.reactions = reactions;
}
+ /**
+ * Gets the guild associated with the reactions.
+ *
+ * @return the guild
+ */
@Override
public Guild guild() {
return thanking.guild();
}
+ /**
+ * Gets the guild ID associated with the reactions.
+ *
+ * @return the guild ID
+ */
@Override
public long guildId() {
return thanking.guildId();
}
+ /**
+ * Checks if the given reaction is a valid reaction.
+ *
+ * @param reaction the message reaction
+ * @return true if the reaction is valid, false otherwise
+ */
public boolean isReaction(MessageReaction reaction) {
if (reaction.getEmoji() instanceof UnicodeEmoji emoji) {
return isReaction(emoji.getAsReactionCode());
@@ -53,6 +79,12 @@ public boolean isReaction(MessageReaction reaction) {
return false;
}
+ /**
+ * Checks if the given reaction string is a valid reaction.
+ *
+ * @param reaction the reaction string
+ * @return true if the reaction is valid, false otherwise
+ */
private boolean isReaction(String reaction) {
if (mainReaction.equals(reaction)) {
return true;
@@ -60,10 +92,20 @@ private boolean isReaction(String reaction) {
return reactions.contains(reaction);
}
+ /**
+ * Checks if the main reaction is an emote.
+ *
+ * @return true if the main reaction is an emote, false otherwise
+ */
public boolean reactionIsEmote() {
return Verifier.isValidId(mainReaction());
}
+ /**
+ * Gets the mention string for the main reaction.
+ *
+ * @return an optional containing the mention string if available, otherwise empty
+ */
public Optional reactionMention() {
if (!reactionIsEmote()) {
return Optional.ofNullable(mainReaction());
@@ -72,10 +114,20 @@ public Optional reactionMention() {
.map(CustomEmoji::getAsMention);
}
+ /**
+ * Gets the main reaction string.
+ *
+ * @return the main reaction string
+ */
public String mainReaction() {
return mainReaction;
}
+ /**
+ * Gets the mentions for the additional reactions.
+ *
+ * @return a list of additional reaction mentions
+ */
public List getAdditionalReactionMentions() {
return reactions.stream()
.map(reaction -> {
@@ -90,6 +142,12 @@ public List getAdditionalReactionMentions() {
.collect(Collectors.toList());
}
+ /**
+ * Adds a new reaction to the set of reactions.
+ *
+ * @param reaction the reaction string
+ * @return true if the reaction was added successfully, false otherwise
+ */
public boolean add(String reaction) {
var result = query("""
INSERT INTO guild_reactions(guild_id, reaction) VALUES (?,?)
@@ -105,6 +163,12 @@ ON CONFLICT(guild_id, reaction)
return result;
}
+ /**
+ * Removes a reaction from the set of reactions.
+ *
+ * @param reaction the reaction string
+ * @return true if the reaction was removed successfully, false otherwise
+ */
public boolean remove(String reaction) {
var result = query("""
DELETE FROM guild_reactions WHERE guild_id = ? AND reaction = ?;
@@ -119,6 +183,12 @@ public boolean remove(String reaction) {
return result;
}
+ /**
+ * Sets the main reaction.
+ *
+ * @param reaction the reaction string
+ * @return true if the main reaction was set successfully, false otherwise
+ */
public boolean mainReaction(String reaction) {
var result = query("""
INSERT INTO thank_settings(guild_id, reaction) VALUES (?,?)
@@ -135,6 +205,11 @@ ON CONFLICT(guild_id)
return result;
}
+ /**
+ * Gets the set of reactions.
+ *
+ * @return the set of reactions
+ */
public Set reactions() {
return reactions;
}
diff --git a/src/main/java/de/chojo/repbot/dao/access/guild/settings/sub/thanking/ReceiverRoles.java b/src/main/java/de/chojo/repbot/dao/access/guild/settings/sub/thanking/ReceiverRoles.java
index d3c9bd367..c59f69996 100644
--- a/src/main/java/de/chojo/repbot/dao/access/guild/settings/sub/thanking/ReceiverRoles.java
+++ b/src/main/java/de/chojo/repbot/dao/access/guild/settings/sub/thanking/ReceiverRoles.java
@@ -10,24 +10,48 @@
import java.util.Set;
+/**
+ * Manages the roles for receivers in a guild.
+ */
public class ReceiverRoles extends RolesHolder {
private final Thanking thanking;
+ /**
+ * Constructs a ReceiverRoles instance.
+ *
+ * @param thanking the thanking settings
+ * @param roleIds the set of role IDs
+ */
public ReceiverRoles(Thanking thanking, Set roleIds) {
super(thanking, roleIds);
this.thanking = thanking;
}
+ /**
+ * Gets the guild associated with the receiver roles.
+ *
+ * @return the guild
+ */
@Override
public Guild guild() {
return thanking.guild();
}
+ /**
+ * Gets the guild ID associated with the receiver roles.
+ *
+ * @return the guild ID
+ */
@Override
public long guildId() {
return thanking.guildId();
}
+ /**
+ * Gets the target table name for receiver roles.
+ *
+ * @return the target table name
+ */
@Override
protected String targetTable() {
return "receiver_roles";
diff --git a/src/main/java/de/chojo/repbot/dao/access/metrics/Commands.java b/src/main/java/de/chojo/repbot/dao/access/metrics/Commands.java
index a57e8d0ad..5511e3c5a 100644
--- a/src/main/java/de/chojo/repbot/dao/access/metrics/Commands.java
+++ b/src/main/java/de/chojo/repbot/dao/access/metrics/Commands.java
@@ -14,16 +14,26 @@
import java.time.LocalDate;
import java.util.Collections;
import java.util.List;
-import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
import static de.chojo.sadu.queries.api.call.Call.call;
+/**
+ * Data access object for handling command metrics.
+ */
public class Commands {
+ /**
+ * Constructs a new Commands instance.
+ */
public Commands() {
}
+ /**
+ * Logs a command execution.
+ *
+ * @param command the command to log
+ */
public void logCommand(String command) {
Query.query("""
INSERT INTO metrics_commands(day, command) VALUES (now()::DATE, ?)
@@ -34,22 +44,57 @@ ON CONFLICT(day,command)
.insert();
}
+ /**
+ * Retrieves command statistics for a specific week.
+ *
+ * @param week the week number
+ * @return the command statistics for the specified week
+ */
public CommandsStatistic week(int week) {
return get("metrics_commands_week", "week", week);
}
+ /**
+ * Retrieves command statistics for a specific month.
+ *
+ * @param month the month number
+ * @return the command statistics for the specified month
+ */
public CommandsStatistic month(int month) {
return get("metrics_commands_month", "month", month);
}
+ /**
+ * Retrieves command execution counts for a specific week.
+ *
+ * @param week the week number
+ * @param count the number of entries to retrieve
+ * @return the command execution counts for the specified week
+ */
public CountsStatistic week(int week, int count) {
return get("metrics_commands_executed_week", "week", week, count);
}
+ /**
+ * Retrieves command execution counts for a specific month.
+ *
+ * @param month the month number
+ * @param count the number of entries to retrieve
+ * @return the command execution counts for the specified month
+ */
public CountsStatistic month(int month, int count) {
return get("metrics_commands_executed_month", "month", month, count);
}
+ /**
+ * Retrieves command execution counts from the database.
+ *
+ * @param table the table name
+ * @param timeframe the timeframe (week or month)
+ * @param offset the offset value
+ * @param count the number of entries to retrieve
+ * @return the command execution counts
+ */
private CountsStatistic get(String table, String timeframe, int offset, int count) {
return Query.query("""
SELECT %s,
@@ -65,6 +110,14 @@ private CountsStatistic get(String table, String timeframe, int offset, int coun
.map(CountsStatistic::new);
}
+ /**
+ * Retrieves command statistics from the database.
+ *
+ * @param table the table name
+ * @param timeframe the timeframe (week or month)
+ * @param offset the offset value
+ * @return the command statistics
+ */
private CommandsStatistic get(String table, String timeframe, int offset) {
return Query
.query("""
@@ -80,6 +133,12 @@ private CommandsStatistic get(String table, String timeframe, int offset) {
.map(this::mapStatistics);
}
+ /**
+ * Maps a list of command statistics to a CommandsStatistic object.
+ *
+ * @param commandStatistics the list of command statistics
+ * @return the mapped CommandsStatistic object
+ */
private CommandsStatistic mapStatistics(List commandStatistics) {
return commandStatistics.stream()
.collect(Collectors.groupingBy(CommandStatistic::date))
diff --git a/src/main/java/de/chojo/repbot/dao/components/GuildHolder.java b/src/main/java/de/chojo/repbot/dao/components/GuildHolder.java
index d065e4a18..9582df3c1 100644
--- a/src/main/java/de/chojo/repbot/dao/components/GuildHolder.java
+++ b/src/main/java/de/chojo/repbot/dao/components/GuildHolder.java
@@ -7,8 +7,22 @@
import net.dv8tion.jda.api.entities.Guild;
+/**
+ * Interface representing a holder for a Guild.
+ */
public interface GuildHolder {
+
+ /**
+ * Gets the Guild associated with this holder.
+ *
+ * @return the Guild
+ */
Guild guild();
+ /**
+ * Gets the ID of the Guild associated with this holder.
+ *
+ * @return the Guild ID
+ */
long guildId();
}
diff --git a/src/main/java/de/chojo/repbot/dao/components/MemberHolder.java b/src/main/java/de/chojo/repbot/dao/components/MemberHolder.java
index cc73f47ce..10ac61486 100644
--- a/src/main/java/de/chojo/repbot/dao/components/MemberHolder.java
+++ b/src/main/java/de/chojo/repbot/dao/components/MemberHolder.java
@@ -9,23 +9,51 @@
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.User;
+/**
+ * Interface representing a holder for a member, providing access to the member, user, and guild information.
+ */
public interface MemberHolder extends UserHolder, GuildHolder {
+ /**
+ * Retrieves the member associated with this holder.
+ *
+ * @return the member
+ */
Member member();
+ /**
+ * Retrieves the ID of the member associated with this holder.
+ *
+ * @return the member ID
+ */
default long memberId() {
return member().getIdLong();
}
+ /**
+ * Retrieves the user associated with this holder.
+ *
+ * @return the user
+ */
@Override
default User user() {
return member().getUser();
}
+ /**
+ * Retrieves the guild associated with this holder.
+ *
+ * @return the guild
+ */
@Override
default Guild guild() {
return member().getGuild();
}
+ /**
+ * Retrieves the ID of the guild associated with this holder.
+ *
+ * @return the guild ID
+ */
@Override
default long guildId(){
return guild().getIdLong();
diff --git a/src/main/java/de/chojo/repbot/dao/components/UserHolder.java b/src/main/java/de/chojo/repbot/dao/components/UserHolder.java
index 0ebdde8c7..2a5b92a8b 100644
--- a/src/main/java/de/chojo/repbot/dao/components/UserHolder.java
+++ b/src/main/java/de/chojo/repbot/dao/components/UserHolder.java
@@ -7,9 +7,22 @@
import net.dv8tion.jda.api.entities.User;
+/**
+ * Interface representing a holder for a user, providing access to the user information.
+ */
public interface UserHolder {
+ /**
+ * Retrieves the user associated with this holder.
+ *
+ * @return the user
+ */
User user();
+ /**
+ * Retrieves the ID of the user associated with this holder.
+ *
+ * @return the user ID
+ */
default long userId() {
return user().getIdLong();
}
diff --git a/src/main/java/de/chojo/repbot/dao/pagination/GuildList.java b/src/main/java/de/chojo/repbot/dao/pagination/GuildList.java
index 3bd08c7e0..1fc403237 100644
--- a/src/main/java/de/chojo/repbot/dao/pagination/GuildList.java
+++ b/src/main/java/de/chojo/repbot/dao/pagination/GuildList.java
@@ -11,7 +11,17 @@
import java.util.function.Function;
import java.util.function.Supplier;
+/**
+ * Class representing a paginated list of guilds.
+ */
public class GuildList extends PageAccess {
+
+ /**
+ * Constructs a new GuildList instance.
+ *
+ * @param pagecount a supplier providing the total number of pages
+ * @param pageSupplier a function providing a list of RepGuild objects for a given page number
+ */
public GuildList(Supplier pagecount, Function> pageSupplier) {
super(pagecount, pageSupplier);
}
diff --git a/src/main/java/de/chojo/repbot/dao/pagination/GuildRanking.java b/src/main/java/de/chojo/repbot/dao/pagination/GuildRanking.java
index 14e2fd239..cd127bcc9 100644
--- a/src/main/java/de/chojo/repbot/dao/pagination/GuildRanking.java
+++ b/src/main/java/de/chojo/repbot/dao/pagination/GuildRanking.java
@@ -11,14 +11,29 @@
import java.util.function.Function;
import java.util.function.Supplier;
+/**
+ * Class representing a paginated list of guild rankings.
+ */
public class GuildRanking extends PageAccess {
private final String title;
+ /**
+ * Constructs a new GuildRanking instance.
+ *
+ * @param title the title of the guild ranking
+ * @param pagecount a supplier providing the total number of pages
+ * @param pageSupplier a function providing a list of RepProfile objects for a given page number
+ */
public GuildRanking(String title, Supplier pagecount, Function> pageSupplier) {
super(pagecount, pageSupplier);
this.title = title;
}
+ /**
+ * Retrieves the title of the guild ranking.
+ *
+ * @return the title of the guild ranking
+ */
public String title() {
return title;
}
diff --git a/src/main/java/de/chojo/repbot/dao/provider/Guilds.java b/src/main/java/de/chojo/repbot/dao/provider/Guilds.java
index 00e6a9826..509dfb23d 100644
--- a/src/main/java/de/chojo/repbot/dao/provider/Guilds.java
+++ b/src/main/java/de/chojo/repbot/dao/provider/Guilds.java
@@ -23,16 +23,30 @@
import static de.chojo.sadu.queries.api.query.Query.query;
import static org.slf4j.LoggerFactory.getLogger;
+/**
+ * Provides access to guild-related data and operations.
+ */
public class Guilds {
private static final Logger log = getLogger(Guilds.class);
private final Cache guilds = CacheBuilder.newBuilder().expireAfterAccess(30, TimeUnit.MINUTES)
.build();
private final Configuration configuration;
+ /**
+ * Constructs a new Guilds instance.
+ *
+ * @param configuration the configuration instance
+ */
public Guilds(Configuration configuration) {
this.configuration = configuration;
}
+ /**
+ * Retrieves a RepGuild instance for the specified guild.
+ *
+ * @param guild the Guild instance
+ * @return the RepGuild instance
+ */
public RepGuild guild(Guild guild) {
try {
return guilds.get(guild.getIdLong(), () -> new RepGuild(guild, configuration)).refresh(guild);
@@ -46,7 +60,7 @@ public RepGuild guild(Guild guild) {
* Gets a guild by id. This guild object might have limited functionality. This object is never cached.
* It should never be used to change settings.
*
- * There is no gurantee that this guild will have any data stored in the database.
+ * There is no guarantee that this guild will have any data stored in the database.
*
* @param id id of guild to create.
* @return repguild created based on an id
@@ -56,6 +70,12 @@ public RepGuild byId(long id) {
return cached != null ? cached : new RepGuildId(id, configuration);
}
+ /**
+ * Retrieves a list of guilds by reputation mode.
+ *
+ * @param mode the reputation mode
+ * @return a list of RepGuild instances
+ */
public List byReputationMode(ReputationMode mode) {
return query("SELECT guild_id FROM guild_settings WHERE reputation_mode = ?")
.single(call().bind(mode.name()))
@@ -63,10 +83,22 @@ public List byReputationMode(ReputationMode mode) {
.all();
}
+ /**
+ * Retrieves a paginated list of guilds.
+ *
+ * @param pageSize the number of guilds per page
+ * @return a GuildList instance
+ */
public GuildList guilds(int pageSize) {
return new GuildList(() -> pages(pageSize), page -> page(pageSize, page));
}
+ /**
+ * Calculates the total number of pages for the given page size.
+ *
+ * @param pageSize the number of guilds per page
+ * @return the total number of pages
+ */
private Integer pages(int pageSize) {
return query("""
SELECT
@@ -80,6 +112,13 @@ private Integer pages(int pageSize) {
.orElse(1);
}
+ /**
+ * Retrieves a list of guilds for the specified page.
+ *
+ * @param pageSize the number of guilds per page
+ * @param page the page number
+ * @return a list of RepGuild instances
+ */
private List page(int pageSize, int page) {
return query("""
SELECT guild_id FROM guilds
@@ -91,6 +130,11 @@ private List page(int pageSize, int page) {
.all();
}
+ /**
+ * Invalidates the cache for the specified guild.
+ *
+ * @param guild the guild ID
+ */
public void invalidate(long guild) {
guilds.invalidate(guild);
}
diff --git a/src/main/java/de/chojo/repbot/dao/provider/Metrics.java b/src/main/java/de/chojo/repbot/dao/provider/Metrics.java
index a5406f4cd..e3f0f3d16 100644
--- a/src/main/java/de/chojo/repbot/dao/provider/Metrics.java
+++ b/src/main/java/de/chojo/repbot/dao/provider/Metrics.java
@@ -14,6 +14,9 @@
import javax.sql.DataSource;
+/**
+ * Provides access to various metrics.
+ */
public class Metrics {
private final Commands commands;
private final Messages messages;
@@ -22,6 +25,11 @@ public class Metrics {
private final Reputation reputation;
private final Service service;
+ /**
+ * Constructs a new Metrics provider with the specified data source.
+ *
+ * @param dataSource the data source to use
+ */
public Metrics(DataSource dataSource) {
commands = new Commands();
messages = new Messages();
@@ -31,26 +39,56 @@ public Metrics(DataSource dataSource) {
service = new Service();
}
+ /**
+ * Returns the Commands metrics.
+ *
+ * @return the Commands metrics
+ */
public Commands commands() {
return commands;
}
+ /**
+ * Returns the Messages metrics.
+ *
+ * @return the Messages metrics
+ */
public Messages messages() {
return messages;
}
+ /**
+ * Returns the Users metrics.
+ *
+ * @return the Users metrics
+ */
public Users users() {
return users;
}
+ /**
+ * Returns the Statistic metrics.
+ *
+ * @return the Statistic metrics
+ */
public Statistic statistic() {
return statistic;
}
+ /**
+ * Returns the Reputation metrics.
+ *
+ * @return the Reputation metrics
+ */
public Reputation reputation() {
return reputation;
}
+ /**
+ * Returns the Service metrics.
+ *
+ * @return the Service metrics
+ */
public Service service() {
return service;
}
diff --git a/src/main/java/de/chojo/repbot/dao/snapshots/AnalyzerTrace.java b/src/main/java/de/chojo/repbot/dao/snapshots/AnalyzerTrace.java
index 36768b197..25fbb9aaa 100644
--- a/src/main/java/de/chojo/repbot/dao/snapshots/AnalyzerTrace.java
+++ b/src/main/java/de/chojo/repbot/dao/snapshots/AnalyzerTrace.java
@@ -15,7 +15,21 @@
import java.util.ArrayList;
import java.util.List;
+/**
+ * Represents a trace of the analyzer, containing the result entry and a list of submit result entries.
+ *
+ * @param resultEntry the result entry of the analyzer
+ * @param submitResultEntries the list of submit result entries
+ */
public record AnalyzerTrace(ResultEntry resultEntry, List submitResultEntries) {
+
+ /**
+ * Builds a list of message embeds representing the analyzer trace.
+ *
+ * @param guild the guild where the trace is being built
+ * @param context the event context
+ * @return a list of message embeds
+ */
public List embed(Guild guild, EventContext context) {
List embeds = new ArrayList<>();
if (resultEntry != null) {
diff --git a/src/main/java/de/chojo/repbot/dao/snapshots/GuildReputationStats.java b/src/main/java/de/chojo/repbot/dao/snapshots/GuildReputationStats.java
index 74e09f1b1..8d67b6bee 100644
--- a/src/main/java/de/chojo/repbot/dao/snapshots/GuildReputationStats.java
+++ b/src/main/java/de/chojo/repbot/dao/snapshots/GuildReputationStats.java
@@ -5,5 +5,13 @@
*/
package de.chojo.repbot.dao.snapshots;
+/**
+ * Record representing the reputation statistics of a guild.
+ *
+ * @param totalReputation the total reputation of the guild
+ * @param weekReputation the reputation gained by the guild in the past week
+ * @param todayReputation the reputation gained by the guild today
+ * @param topChannelId the ID of the top channel in the guild
+ */
public record GuildReputationStats(int totalReputation, int weekReputation, int todayReputation, long topChannelId) {
}
diff --git a/src/main/java/de/chojo/repbot/dao/snapshots/RepProfile.java b/src/main/java/de/chojo/repbot/dao/snapshots/RepProfile.java
index 4069edcd5..afec89275 100644
--- a/src/main/java/de/chojo/repbot/dao/snapshots/RepProfile.java
+++ b/src/main/java/de/chojo/repbot/dao/snapshots/RepProfile.java
@@ -27,16 +27,39 @@
/**
* Snapshot of a user reputation profile.
+ *
+ * @param repUser the reputation user
+ * @param rank the rank of the user
+ * @param rankDonated the rank based on donations
+ * @param userId the ID of the user
+ * @param reputation the reputation points of the user
+ * @param repOffset the reputation offset
+ * @param rawReputation the raw reputation points
+ * @param donated the amount donated
*/
public record RepProfile(RepUser repUser, long rank, long rankDonated, long userId, long reputation, long repOffset,
- long rawReputation,
- long donated) {
+ long rawReputation, long donated) {
private static final int BAR_SIZE = 20;
+ /**
+ * Creates an empty RepProfile for the specified user.
+ *
+ * @param repuser the reputation user
+ * @param user the user
+ * @return an empty RepProfile
+ */
public static RepProfile empty(RepUser repuser, User user) {
return new RepProfile(repuser, 0, user.getIdLong(), 0, 0, 0, 0, 0);
}
+ /**
+ * Builds a RepProfile from the given database row.
+ *
+ * @param repuser the reputation user
+ * @param rs the database row
+ * @return a RepProfile
+ * @throws SQLException if a database access error occurs
+ */
public static RepProfile buildProfile(RepUser repuser, Row rs) throws SQLException {
return new RepProfile(repuser,
rs.getLong("rank"),
@@ -49,6 +72,13 @@ public static RepProfile buildProfile(RepUser repuser, Row rs) throws SQLExcepti
);
}
+ /**
+ * Builds a RepProfile for received ranking from the given database row.
+ *
+ * @param rs the database row
+ * @return a RepProfile
+ * @throws SQLException if a database access error occurs
+ */
public static RepProfile buildReceivedRanking(Row rs) throws SQLException {
return new RepProfile(null,
rs.getLong("rank"),
@@ -61,16 +91,36 @@ public static RepProfile buildReceivedRanking(Row rs) throws SQLException {
);
}
+ /**
+ * Generates a fancy string representation of the profile.
+ *
+ * @param maxRank the maximum rank
+ * @return a fancy string representation
+ */
public String fancyString(int maxRank) {
var length = String.valueOf(maxRank).length();
var rank = StringUtils.rightPad(String.valueOf(this.rank), length);
return "`" + rank + "` **|** " + MentionUtil.user(userId) + " ➜ " + reputation;
}
+ /**
+ * Generates a public profile message embed.
+ *
+ * @param configuration the configuration
+ * @param localizer the localization context
+ * @return a public profile message embed
+ */
public MessageEmbed publicProfile(Configuration configuration, LocalizationContext localizer) {
return getBaseBuilder(configuration, localizer).build();
}
+ /**
+ * Generates an admin profile message embed.
+ *
+ * @param configuration the configuration
+ * @param localizer the localization context
+ * @return an admin profile message embed
+ */
public MessageEmbed adminProfile(Configuration configuration, LocalizationContext localizer) {
var build = getBaseBuilder(configuration, localizer);
build.addField("words.rawReputation", String.valueOf(rawReputation()), true)
@@ -79,6 +129,13 @@ public MessageEmbed adminProfile(Configuration configuration, LocalizationContex
return build.build();
}
+ /**
+ * Creates a base embed builder for the profile.
+ *
+ * @param configuration the configuration
+ * @param localizer the localization context
+ * @return an embed builder
+ */
private EmbedBuilder getBaseBuilder(Configuration configuration, LocalizationContext localizer) {
var ranks = repUser.reputation().repGuild().settings().ranks();
var current = ranks.currentRank(repUser);
@@ -108,6 +165,12 @@ private EmbedBuilder getBaseBuilder(Configuration configuration, LocalizationCon
return build;
}
+ /**
+ * Resolves the member associated with this profile in the given guild.
+ *
+ * @param guild the guild
+ * @return an optional containing the member if found, otherwise empty
+ */
public Optional resolveMember(Guild guild) {
try {
return Optional.ofNullable(guild.retrieveMemberById(userId()).complete());
diff --git a/src/main/java/de/chojo/repbot/dao/snapshots/analyzer/ResultSnapshot.java b/src/main/java/de/chojo/repbot/dao/snapshots/analyzer/ResultSnapshot.java
index c777773cc..d1983bf77 100644
--- a/src/main/java/de/chojo/repbot/dao/snapshots/analyzer/ResultSnapshot.java
+++ b/src/main/java/de/chojo/repbot/dao/snapshots/analyzer/ResultSnapshot.java
@@ -10,7 +10,18 @@
import de.chojo.repbot.dao.snapshots.ResultEntry;
import net.dv8tion.jda.api.entities.Guild;
+/**
+ * Interface for result snapshots.
+ * This interface is used to add result entries to a snapshot with a localized embed builder.
+ */
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "@class")
public interface ResultSnapshot {
+ /**
+ * Adds a result entry to the snapshot.
+ *
+ * @param guild the guild where the result entry is being added
+ * @param entry the result entry to add
+ * @param builder the localized embed builder to use
+ */
void add(Guild guild, ResultEntry entry, LocalizedEmbedBuilder builder);
}
diff --git a/src/main/java/de/chojo/repbot/dao/snapshots/analyzer/match/AnswerResultSnapshot.java b/src/main/java/de/chojo/repbot/dao/snapshots/analyzer/match/AnswerResultSnapshot.java
index 1e86259d4..9e6040248 100644
--- a/src/main/java/de/chojo/repbot/dao/snapshots/analyzer/match/AnswerResultSnapshot.java
+++ b/src/main/java/de/chojo/repbot/dao/snapshots/analyzer/match/AnswerResultSnapshot.java
@@ -16,9 +16,20 @@
import java.util.List;
+/**
+ * Snapshot class for storing the result of an answer match.
+ */
public class AnswerResultSnapshot extends DirectResultSnapshot implements ResultSnapshot {
private final long messageId;
+ /**
+ * Constructs an AnswerResultSnapshot instance.
+ *
+ * @param donorId the ID of the donor
+ * @param match the match string
+ * @param receivers the list of receiver IDs
+ * @param messageId the ID of the message
+ */
@JsonCreator
public AnswerResultSnapshot(@JsonProperty("donorId") long donorId,
@JsonProperty("match") String match,
@@ -28,6 +39,13 @@ public AnswerResultSnapshot(@JsonProperty("donorId") long donorId,
this.messageId = messageId;
}
+ /**
+ * Adds the result entry to the localized embed builder.
+ *
+ * @param guild the guild
+ * @param entry the result entry
+ * @param builder the localized embed builder
+ */
@Override
public void add(Guild guild, ResultEntry entry, LocalizedEmbedBuilder builder) {
super.add(guild, entry, builder);
diff --git a/src/main/java/de/chojo/repbot/dao/snapshots/analyzer/match/DirectResultSnapshot.java b/src/main/java/de/chojo/repbot/dao/snapshots/analyzer/match/DirectResultSnapshot.java
index 502f2167f..fee898a33 100644
--- a/src/main/java/de/chojo/repbot/dao/snapshots/analyzer/match/DirectResultSnapshot.java
+++ b/src/main/java/de/chojo/repbot/dao/snapshots/analyzer/match/DirectResultSnapshot.java
@@ -17,9 +17,20 @@
import java.util.List;
import java.util.stream.Collectors;
+/**
+ * Represents a snapshot of a direct result match.
+ */
public class DirectResultSnapshot extends MatchResultSnapshot implements ResultSnapshot {
private final List receivers;
+ /**
+ * Constructs a new DirectResultSnapshot.
+ *
+ * @param thankType the type of thank
+ * @param donorId the ID of the donor
+ * @param match the match string
+ * @param receivers the list of receiver IDs
+ */
@JsonCreator
public DirectResultSnapshot(@JsonProperty("thankType") ThankType thankType,
@JsonProperty("donorId") long donorId,
@@ -29,10 +40,22 @@ public DirectResultSnapshot(@JsonProperty("thankType") ThankType thankType,
this.receivers = receivers;
}
+ /**
+ * Retrieves the list of receiver IDs.
+ *
+ * @return the list of receiver IDs
+ */
public List receivers() {
return receivers;
}
+ /**
+ * Adds the result entry to the localized embed builder.
+ *
+ * @param guild the guild
+ * @param entry the result entry
+ * @param builder the localized embed builder
+ */
@Override
public void add(Guild guild, ResultEntry entry, LocalizedEmbedBuilder builder) {
super.add(guild, entry, builder);
diff --git a/src/main/java/de/chojo/repbot/dao/snapshots/analyzer/match/FuzzyResultSnapshot.java b/src/main/java/de/chojo/repbot/dao/snapshots/analyzer/match/FuzzyResultSnapshot.java
index b6b859d01..a68ad0d5d 100644
--- a/src/main/java/de/chojo/repbot/dao/snapshots/analyzer/match/FuzzyResultSnapshot.java
+++ b/src/main/java/de/chojo/repbot/dao/snapshots/analyzer/match/FuzzyResultSnapshot.java
@@ -18,10 +18,21 @@
import java.util.List;
import java.util.stream.Collectors;
+/**
+ * Represents a snapshot of fuzzy match results.
+ */
public class FuzzyResultSnapshot extends MatchResultSnapshot implements ResultSnapshot {
private final List thankwords;
private final List memberMatches;
+ /**
+ * Constructs a new FuzzyResultSnapshot instance.
+ *
+ * @param donor the ID of the donor
+ * @param match the match string
+ * @param thankwords the list of thank words
+ * @param memberMatches the list of member matches
+ */
@JsonCreator
public FuzzyResultSnapshot(@JsonProperty("donor") long donor,
@JsonProperty("match") String match,
@@ -32,6 +43,13 @@ public FuzzyResultSnapshot(@JsonProperty("donor") long donor,
this.memberMatches = memberMatches;
}
+ /**
+ * Adds the result entry to the localized embed builder.
+ *
+ * @param guild the guild
+ * @param entry the result entry
+ * @param builder the localized embed builder
+ */
@Override
public void add(Guild guild, ResultEntry entry, LocalizedEmbedBuilder builder) {
super.add(guild, entry, builder);
diff --git a/src/main/java/de/chojo/repbot/dao/snapshots/analyzer/match/MatchResultSnapshot.java b/src/main/java/de/chojo/repbot/dao/snapshots/analyzer/match/MatchResultSnapshot.java
index 46b040cd9..903e18202 100644
--- a/src/main/java/de/chojo/repbot/dao/snapshots/analyzer/match/MatchResultSnapshot.java
+++ b/src/main/java/de/chojo/repbot/dao/snapshots/analyzer/match/MatchResultSnapshot.java
@@ -13,29 +13,61 @@
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.User;
+/**
+ * Abstract class representing a snapshot of a match result.
+ */
public abstract class MatchResultSnapshot implements ResultSnapshot {
private final ThankType thankType;
private final long donorId;
private final String match;
+ /**
+ * Constructs a new MatchResultSnapshot with the specified thank type, donor ID, and match.
+ *
+ * @param thankType the type of thank
+ * @param donorId the ID of the donor
+ * @param match the matched string
+ */
public MatchResultSnapshot(ThankType thankType, long donorId, String match) {
this.thankType = thankType;
this.donorId = donorId;
this.match = match;
}
+ /**
+ * Returns the type of thank.
+ *
+ * @return the thank type
+ */
public ThankType thankType() {
return thankType;
}
+ /**
+ * Returns the ID of the donor.
+ *
+ * @return the donor ID
+ */
public long donorId() {
return donorId;
}
+ /**
+ * Returns the matched string.
+ *
+ * @return the match
+ */
public String match() {
return match;
}
+ /**
+ * Adds the match result information to the provided LocalizedEmbedBuilder.
+ *
+ * @param guild the guild
+ * @param entry the result entry
+ * @param builder the LocalizedEmbedBuilder to add information to
+ */
@Override
public void add(Guild guild, ResultEntry entry, LocalizedEmbedBuilder builder) {
builder.setTitle(thankType.nameLocaleKey())
diff --git a/src/main/java/de/chojo/repbot/dao/snapshots/statistics/ChartProvider.java b/src/main/java/de/chojo/repbot/dao/snapshots/statistics/ChartProvider.java
index 29ea9001d..6af770ea6 100644
--- a/src/main/java/de/chojo/repbot/dao/snapshots/statistics/ChartProvider.java
+++ b/src/main/java/de/chojo/repbot/dao/snapshots/statistics/ChartProvider.java
@@ -5,7 +5,16 @@
*/
package de.chojo.repbot.dao.snapshots.statistics;
+/**
+ * Interface for providing chart data.
+ */
public interface ChartProvider {
+ /**
+ * Generates a chart with the specified title.
+ *
+ * @param title the title of the chart
+ * @return a byte array representing the chart
+ */
byte[] getChart(String title);
}
diff --git a/src/main/java/de/chojo/repbot/dao/snapshots/statistics/CommandStatistic.java b/src/main/java/de/chojo/repbot/dao/snapshots/statistics/CommandStatistic.java
index 11ae30126..2a696f266 100644
--- a/src/main/java/de/chojo/repbot/dao/snapshots/statistics/CommandStatistic.java
+++ b/src/main/java/de/chojo/repbot/dao/snapshots/statistics/CommandStatistic.java
@@ -5,14 +5,28 @@
*/
package de.chojo.repbot.dao.snapshots.statistics;
-
import de.chojo.sadu.mapper.wrapper.Row;
import java.sql.SQLException;
import java.time.LocalDate;
+/**
+ * Record class representing a command statistic.
+ *
+ * @param date the date of the statistic
+ * @param command the command name
+ * @param count the count of the command executions
+ */
public record CommandStatistic(LocalDate date, String command, int count) {
+ /**
+ * Builds a CommandStatistic instance from a database row.
+ *
+ * @param rs the database row
+ * @param dateKey the key for the date column
+ * @return a CommandStatistic instance
+ * @throws SQLException if a database access error occurs
+ */
public static CommandStatistic build(Row rs, String dateKey) throws SQLException {
return new CommandStatistic(rs.getDate(dateKey).toLocalDate(),
rs.getString("command"),
diff --git a/src/main/java/de/chojo/repbot/dao/snapshots/statistics/CommandsStatistic.java b/src/main/java/de/chojo/repbot/dao/snapshots/statistics/CommandsStatistic.java
index 1cb103d25..e35740b59 100644
--- a/src/main/java/de/chojo/repbot/dao/snapshots/statistics/CommandsStatistic.java
+++ b/src/main/java/de/chojo/repbot/dao/snapshots/statistics/CommandsStatistic.java
@@ -14,8 +14,20 @@
import java.time.LocalDate;
import java.util.List;
+/**
+ * Represents the statistics of commands executed on a specific date.
+ *
+ * @param date the date of the statistics
+ * @param commands the list of command statistics
+ */
public record CommandsStatistic(LocalDate date, List commands) implements ChartProvider {
+ /**
+ * Generates a chart representing the command statistics.
+ *
+ * @param title the title of the chart
+ * @return a byte array containing the chart image in PNG format
+ */
@Override
public byte[] getChart(String title) {
var categorySeries = new CategoryChartBuilder().width(1200).height(600)
diff --git a/src/main/java/de/chojo/repbot/dao/snapshots/statistics/CountStatistics.java b/src/main/java/de/chojo/repbot/dao/snapshots/statistics/CountStatistics.java
index abbdbbb4e..72d457e62 100644
--- a/src/main/java/de/chojo/repbot/dao/snapshots/statistics/CountStatistics.java
+++ b/src/main/java/de/chojo/repbot/dao/snapshots/statistics/CountStatistics.java
@@ -11,17 +11,45 @@
import java.sql.SQLException;
import java.time.LocalDateTime;
+/**
+ * Represents a count statistic with a date and count value.
+ *
+ * @param date the date of the statistic
+ * @param count the count value of the statistic
+ */
public record CountStatistics(LocalDateTime date, int count) implements Comparable {
+ /**
+ * Builds a CountStatistics instance from a database row using the specified date key.
+ *
+ * @param rs the database row
+ * @param dateKey the key for the date column
+ * @return a new CountStatistics instance
+ * @throws SQLException if a database access error occurs
+ */
public static CountStatistics build(Row rs, String dateKey) throws SQLException {
return build(rs, "count", dateKey);
}
+ /**
+ * Builds a CountStatistics instance from a database row using the specified count and date keys.
+ *
+ * @param rs the database row
+ * @param countKey the key for the count column
+ * @param dateKey the key for the date column
+ * @return a new CountStatistics instance
+ * @throws SQLException if a database access error occurs
+ */
public static CountStatistics build(Row rs, String countKey, String dateKey) throws SQLException {
- return new CountStatistics(rs.getTimestamp(dateKey).toLocalDateTime(),
- rs.getInt(countKey));
+ return new CountStatistics(rs.getTimestamp(dateKey).toLocalDateTime(), rs.getInt(countKey));
}
+ /**
+ * Compares this CountStatistics instance with another based on the date.
+ *
+ * @param o the other CountStatistics instance
+ * @return a negative integer, zero, or a positive integer as this instance is less than, equal to, or greater than the specified instance
+ */
@Override
public int compareTo(@NotNull CountStatistics o) {
return date().compareTo(o.date());
diff --git a/src/main/java/de/chojo/repbot/dao/snapshots/statistics/CountsStatistic.java b/src/main/java/de/chojo/repbot/dao/snapshots/statistics/CountsStatistic.java
index ab9223811..c1091167d 100644
--- a/src/main/java/de/chojo/repbot/dao/snapshots/statistics/CountsStatistic.java
+++ b/src/main/java/de/chojo/repbot/dao/snapshots/statistics/CountsStatistic.java
@@ -17,9 +17,19 @@
import java.util.Date;
import java.util.List;
+/**
+ * Represents a statistic of counts over time and provides a method to generate a chart.
+ *
+ * @param stats the list of count statistics
+ */
public record CountsStatistic(List stats) implements ChartProvider {
-
+ /**
+ * Gets the count statistics at the specified index.
+ *
+ * @param index the index of the count statistics
+ * @return the count statistics at the specified index, or a default value if the list is empty
+ */
public CountStatistics get(int index) {
if (stats.isEmpty()) {
return new CountStatistics(LocalDateTime.MIN, 0);
@@ -27,6 +37,12 @@ public CountStatistics get(int index) {
return stats.get(index);
}
+ /**
+ * Generates a chart representing the count statistics.
+ *
+ * @param title the title of the chart
+ * @return a byte array representing the chart in PNG format
+ */
@Override
public byte[] getChart(String title) {
var categorySeries = new XYChartBuilder().width(1200).height(600)
@@ -58,6 +74,12 @@ public byte[] getChart(String title) {
}
}
+ /**
+ * Converts a LocalDateTime to a Date object.
+ *
+ * @param date the LocalDateTime to convert
+ * @return the corresponding Date object
+ */
private Date toDate(LocalDateTime date) {
return new Date(date.toEpochSecond(ZoneOffset.UTC) * 1000);
}
diff --git a/src/main/java/de/chojo/repbot/dao/snapshots/statistics/LabeledCountStatistic.java b/src/main/java/de/chojo/repbot/dao/snapshots/statistics/LabeledCountStatistic.java
index 924a012e6..ba487004b 100644
--- a/src/main/java/de/chojo/repbot/dao/snapshots/statistics/LabeledCountStatistic.java
+++ b/src/main/java/de/chojo/repbot/dao/snapshots/statistics/LabeledCountStatistic.java
@@ -19,8 +19,19 @@
import java.util.List;
import java.util.Map;
+/**
+ * Represents a labeled count statistic and provides chart generation functionality.
+ *
+ * @param stats a map containing labels and their corresponding list of CountStatistics
+ */
public record LabeledCountStatistic(Map> stats) implements ChartProvider {
+ /**
+ * Generates a chart with the given title.
+ *
+ * @param title the title of the chart
+ * @return a byte array representing the chart in PNG format
+ */
@Override
public byte[] getChart(String title) {
var categorySeries = new XYChartBuilder().width(1200).height(600)
@@ -52,6 +63,12 @@ public byte[] getChart(String title) {
}
}
+ /**
+ * Converts a LocalDateTime to a Date.
+ *
+ * @param date the LocalDateTime to convert
+ * @return the corresponding Date
+ */
private Date toDate(LocalDateTime date) {
return new Date(date.toEpochSecond(ZoneOffset.UTC) * 1000);
}
diff --git a/src/main/java/de/chojo/repbot/dao/snapshots/statistics/builder/LabeledCountStatisticBuilder.java b/src/main/java/de/chojo/repbot/dao/snapshots/statistics/builder/LabeledCountStatisticBuilder.java
index 0c79e46bc..a963e4114 100644
--- a/src/main/java/de/chojo/repbot/dao/snapshots/statistics/builder/LabeledCountStatisticBuilder.java
+++ b/src/main/java/de/chojo/repbot/dao/snapshots/statistics/builder/LabeledCountStatisticBuilder.java
@@ -13,14 +13,29 @@
import java.util.List;
import java.util.Map;
+/**
+ * Builder class for creating LabeledCountStatistic instances.
+ */
public class LabeledCountStatisticBuilder {
private final Map> stats = new LinkedHashMap<>();
+ /**
+ * Adds a CountStatistics instance to the builder with the specified label.
+ *
+ * @param label the label for the statistics
+ * @param statistic the CountStatistics instance to add
+ * @return the current instance of LabeledCountStatisticBuilder
+ */
public LabeledCountStatisticBuilder add(String label, CountStatistics statistic) {
stats.computeIfAbsent(label, key -> new ArrayList<>()).add(statistic);
return this;
}
+ /**
+ * Builds and returns a LabeledCountStatistic instance with the accumulated statistics.
+ *
+ * @return a new LabeledCountStatistic instance
+ */
public LabeledCountStatistic build() {
return new LabeledCountStatistic(stats);
}
diff --git a/src/main/java/de/chojo/repbot/listener/LogListener.java b/src/main/java/de/chojo/repbot/listener/LogListener.java
index 3ede75d1c..fab311d95 100644
--- a/src/main/java/de/chojo/repbot/listener/LogListener.java
+++ b/src/main/java/de/chojo/repbot/listener/LogListener.java
@@ -29,6 +29,9 @@
import static org.slf4j.LoggerFactory.getLogger;
+/**
+ * Listener for logging various events related to guilds and sessions.
+ */
public class LogListener extends ListenerAdapter implements Runnable {
private static final Logger log = getLogger(LogListener.class);
private final Map disconnected = new HashMap<>();
@@ -36,12 +39,23 @@ public class LogListener extends ListenerAdapter implements Runnable {
private LogListener() {
}
+ /**
+ * Creates a new LogListener and schedules it to run at a fixed rate.
+ *
+ * @param service the ScheduledExecutorService to use for scheduling
+ * @return a new LogListener instance
+ */
public static LogListener create(ScheduledExecutorService service) {
var logListener = new LogListener();
service.scheduleAtFixedRate(logListener, 60, 60, TimeUnit.SECONDS);
return logListener;
}
+ /**
+ * Handles the event when the bot joins a guild.
+ *
+ * @param event the GuildJoinEvent
+ */
@Override
public void onGuildJoin(@Nonnull GuildJoinEvent event) {
log.info(LogNotify.STATUS, "RepBot joined guild {} on shard {}.",
@@ -49,6 +63,11 @@ public void onGuildJoin(@Nonnull GuildJoinEvent event) {
event.getJDA().getShardInfo().getShardId());
}
+ /**
+ * Handles the event when the bot leaves a guild.
+ *
+ * @param event the GuildLeaveEvent
+ */
@Override
public void onGuildLeave(@Nonnull GuildLeaveEvent event) {
log.info(LogNotify.STATUS, "RepBot left guild {} on shard {}.",
@@ -56,22 +75,42 @@ public void onGuildLeave(@Nonnull GuildLeaveEvent event) {
event.getJDA().getShardInfo().getShardId());
}
+ /**
+ * Handles the event when a session disconnects.
+ *
+ * @param event the SessionDisconnectEvent
+ */
@Override
public void onSessionDisconnect(@NotNull SessionDisconnectEvent event) {
disconnected.put(event.getJDA().getShardInfo().getShardId(), Instant.now());
log.debug("Shard {} disconnected.", event.getJDA().getShardInfo().getShardId());
}
+ /**
+ * Handles the event when a session is recreated.
+ *
+ * @param event the SessionRecreateEvent
+ */
@Override
public void onSessionRecreate(@NotNull SessionRecreateEvent event) {
handleShardReconnect(event.getJDA());
}
+ /**
+ * Handles the event when a session resumes.
+ *
+ * @param event the SessionResumeEvent
+ */
@Override
public void onSessionResume(@NotNull SessionResumeEvent event) {
handleShardReconnect(event.getJDA());
}
+ /**
+ * Handles shard reconnection logic.
+ *
+ * @param jda the JDA instance
+ */
private void handleShardReconnect(JDA jda) {
var shardId = jda.getShardInfo().getShardId();
var seconds = Duration.between(
@@ -87,6 +126,11 @@ private void handleShardReconnect(JDA jda) {
}
}
+ /**
+ * Handles the event when the bot is ready.
+ *
+ * @param event the ReadyEvent
+ */
@Override
public void onReady(@Nonnull ReadyEvent event) {
handleShardReconnect(event.getJDA());
@@ -96,6 +140,9 @@ public void onReady(@Nonnull ReadyEvent event) {
event.getGuildTotalCount());
}
+ /**
+ * Periodically checks for disconnected shards and logs a warning if any are found.
+ */
@Override
public void run() {
if (disconnected.isEmpty()) return;
diff --git a/src/main/java/de/chojo/repbot/listener/ReactionListener.java b/src/main/java/de/chojo/repbot/listener/ReactionListener.java
index 3757468b4..5ada1e912 100644
--- a/src/main/java/de/chojo/repbot/listener/ReactionListener.java
+++ b/src/main/java/de/chojo/repbot/listener/ReactionListener.java
@@ -40,6 +40,9 @@
import static org.slf4j.LoggerFactory.getLogger;
+/**
+ * Listener for handling message reaction events in a guild.
+ */
public class ReactionListener extends ListenerAdapter {
private static final int REACTION_COOLDOWN = 30;
private static final Logger log = getLogger(ReactionListener.class);
@@ -50,6 +53,14 @@ public class ReactionListener extends ListenerAdapter {
private final Cache lastReaction = CacheBuilder.newBuilder().expireAfterAccess(60, TimeUnit.SECONDS)
.build();
+ /**
+ * Constructs a ReactionListener.
+ *
+ * @param guilds the guilds provider
+ * @param localizer the localizer for localization
+ * @param reputationService the reputation service
+ * @param configuration the configuration settings
+ */
public ReactionListener(Guilds guilds, ILocalizer localizer, ReputationService reputationService, Configuration configuration) {
this.guilds = guilds;
this.localizer = localizer;
@@ -57,6 +68,11 @@ public ReactionListener(Guilds guilds, ILocalizer localizer, ReputationService r
this.configuration = configuration;
}
+ /**
+ * Handles the event when a reaction is added to a message.
+ *
+ * @param event the message reaction add event
+ */
@Override
public void onMessageReactionAdd(@NotNull MessageReactionAddEvent event) {
if (event.getUser().isBot() || !event.isFromGuild()) return;
@@ -118,7 +134,11 @@ public void onMessageReactionAdd(@NotNull MessageReactionAddEvent event) {
}
}
-
+ /**
+ * Handles the event when a reaction emoji is removed from a message.
+ *
+ * @param event the message reaction remove emoji event
+ */
@Override
public void onMessageReactionRemoveEmoji(@NotNull MessageReactionRemoveEmojiEvent event) {
if (!event.isFromGuild()) return;
@@ -129,6 +149,11 @@ public void onMessageReactionRemoveEmoji(@NotNull MessageReactionRemoveEmojiEven
.forEach(ReputationLogEntry::delete);
}
+ /**
+ * Handles the event when a reaction is removed from a message.
+ *
+ * @param event the message reaction remove event
+ */
@Override
public void onMessageReactionRemove(@NotNull MessageReactionRemoveEvent event) {
if (!event.isFromGuild()) return;
@@ -147,6 +172,11 @@ public void onMessageReactionRemove(@NotNull MessageReactionRemoveEvent event) {
}
}
+ /**
+ * Handles the event when all reactions are removed from a message.
+ *
+ * @param event the message reaction remove all event
+ */
@Override
public void onMessageReactionRemoveAll(@NotNull MessageReactionRemoveAllEvent event) {
guilds.guild(event.getGuild()).reputation().log().messageLog(event.getMessageIdLong(), 50).stream()
@@ -154,6 +184,12 @@ public void onMessageReactionRemoveAll(@NotNull MessageReactionRemoveAllEvent ev
.forEach(ReputationLogEntry::delete);
}
+ /**
+ * Checks if the member is on cooldown for reacting.
+ *
+ * @param member the member to check
+ * @return true if the member is on cooldown, false otherwise
+ */
public boolean isCooldown(Member member) {
try {
return lastReaction.get(member.getIdLong(), () -> Instant.MIN)
@@ -164,6 +200,11 @@ public boolean isCooldown(Member member) {
return true;
}
+ /**
+ * Records the time when the member reacted.
+ *
+ * @param member the member who reacted
+ */
public void reacted(Member member) {
lastReaction.put(member.getIdLong(), Instant.now());
}
diff --git a/src/main/java/de/chojo/repbot/service/AnalyzerService.java b/src/main/java/de/chojo/repbot/service/AnalyzerService.java
index 76874e76b..302255e65 100644
--- a/src/main/java/de/chojo/repbot/service/AnalyzerService.java
+++ b/src/main/java/de/chojo/repbot/service/AnalyzerService.java
@@ -5,24 +5,40 @@
*/
package de.chojo.repbot.service;
-import de.chojo.repbot.config.Configuration;
import de.chojo.repbot.dao.access.Analyzer;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
+/**
+ * Service for running the analyzer at scheduled intervals.
+ */
public class AnalyzerService implements Runnable {
private final Analyzer analyzer;
+ /**
+ * Constructs an AnalyzerService with the specified analyzer.
+ *
+ * @param analyzer the analyzer to be used by the service
+ */
private AnalyzerService(Analyzer analyzer) {
this.analyzer = analyzer;
}
+ /**
+ * Creates and schedules an AnalyzerService.
+ *
+ * @param executorService the executor service to schedule the analyzer service
+ * @param analyzer the analyzer to be used by the service
+ */
public static void create(ScheduledExecutorService executorService, Analyzer analyzer) {
var analyzerService = new AnalyzerService(analyzer);
executorService.scheduleAtFixedRate(analyzerService, 10, 60, TimeUnit.MINUTES);
}
+ /**
+ * Runs the analyzer cleanup process.
+ */
@Override
public void run() {
analyzer.cleanup();
diff --git a/src/main/java/de/chojo/repbot/service/GdprService.java b/src/main/java/de/chojo/repbot/service/GdprService.java
index d54414619..4bf8c88c6 100644
--- a/src/main/java/de/chojo/repbot/service/GdprService.java
+++ b/src/main/java/de/chojo/repbot/service/GdprService.java
@@ -21,6 +21,9 @@
import static org.slf4j.LoggerFactory.getLogger;
+/**
+ * Service for handling GDPR-related tasks.
+ */
public class GdprService implements Runnable {
private static final Logger log = getLogger(GdprService.class);
private final ShardManager shardManager;
@@ -28,6 +31,14 @@ public class GdprService implements Runnable {
private final Guilds guilds;
private final Gdpr gdpr;
+ /**
+ * Constructs a new GdprService instance.
+ *
+ * @param shardManager the ShardManager instance
+ * @param guilds the Guilds instance
+ * @param gdpr the Gdpr instance
+ * @param executorService the ExecutorService instance
+ */
private GdprService(ShardManager shardManager, Guilds guilds, Gdpr gdpr, ExecutorService executorService) {
this.shardManager = shardManager;
this.guilds = guilds;
@@ -35,6 +46,15 @@ private GdprService(ShardManager shardManager, Guilds guilds, Gdpr gdpr, Executo
this.executorService = executorService;
}
+ /**
+ * Creates and schedules a new GdprService instance.
+ *
+ * @param shardManager the ShardManager instance
+ * @param guilds the Guilds instance
+ * @param gdpr the Gdpr instance
+ * @param scheduledExecutorService the ScheduledExecutorService instance
+ * @return the created GdprService instance
+ */
public static GdprService of(ShardManager shardManager, Guilds guilds, Gdpr gdpr,
ScheduledExecutorService scheduledExecutorService) {
var service = new GdprService(shardManager, guilds, gdpr, scheduledExecutorService);
@@ -42,6 +62,9 @@ public static GdprService of(ShardManager shardManager, Guilds guilds, Gdpr gdpr
return service;
}
+ /**
+ * Runs the GDPR service tasks.
+ */
@Override
public void run() {
var reportRequests = gdpr.getReportRequests(shardManager);
@@ -62,7 +85,12 @@ public void run() {
cleanupGuilds();
}
-
+ /**
+ * Cleans up user data for a specific guild.
+ *
+ * @param guild the Guild instance
+ * @return a CompletableFuture with the number of pruned users
+ */
public CompletableFuture cleanupGuildUsers(Guild guild) {
return CompletableFuture.supplyAsync(() -> {
log.info("Guild prune was started on {}", guild.getId());
@@ -83,11 +111,20 @@ public CompletableFuture cleanupGuildUsers(Guild guild) {
}, executorService);
}
+ /**
+ * Cleans up user data for a specific user in a guild.
+ *
+ * @param guild the Guild instance
+ * @param user the user ID
+ */
public void cleanupGuildUser(Guild guild, Long user) {
log.info("User data of {} was pruned on guild {}.", user, guild.getIdLong());
CompletableFuture.runAsync(() -> RemovalTask.anonymExecute(guild.getIdLong(), user), executorService);
}
+ /**
+ * Cleans up guilds by checking their status and updating their GDPR deletion queue.
+ */
private void cleanupGuilds() {
for (var page : guilds.guilds(100)) {
for (var guild : page) {
diff --git a/src/main/java/de/chojo/repbot/service/MetricService.java b/src/main/java/de/chojo/repbot/service/MetricService.java
index ece8c15a4..351081640 100644
--- a/src/main/java/de/chojo/repbot/service/MetricService.java
+++ b/src/main/java/de/chojo/repbot/service/MetricService.java
@@ -14,13 +14,28 @@
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
+/**
+ * Service for handling metric-related tasks.
+ */
public class MetricService implements Runnable {
private final Metrics metrics;
+ /**
+ * Constructs a new MetricService with the specified metrics provider.
+ *
+ * @param metrics the metrics provider
+ */
public MetricService(Metrics metrics) {
this.metrics = metrics;
}
+ /**
+ * Creates and schedules a new MetricService.
+ *
+ * @param executorService the executor service to schedule the task
+ * @param metrics the metrics provider
+ * @return the created MetricService
+ */
public static MetricService create(ScheduledExecutorService executorService, Metrics metrics) {
var now = ZonedDateTime.now(ZoneOffset.UTC);
var base = now.toLocalDate().atStartOfDay().plus(1, ChronoUnit.DAYS).plus(1, ChronoUnit.HOURS)
@@ -31,6 +46,9 @@ public static MetricService create(ScheduledExecutorService executorService, Met
return service;
}
+ /**
+ * Runs the metric saving tasks.
+ */
@Override
public void run() {
metrics.reputation().saveRepCounts();
diff --git a/src/main/java/de/chojo/repbot/service/PresenceService.java b/src/main/java/de/chojo/repbot/service/PresenceService.java
index 265577493..9e5b13ff4 100644
--- a/src/main/java/de/chojo/repbot/service/PresenceService.java
+++ b/src/main/java/de/chojo/repbot/service/PresenceService.java
@@ -17,18 +17,36 @@
import static org.slf4j.LoggerFactory.getLogger;
+/**
+ * Service for managing the bot's presence.
+ */
public class PresenceService implements Runnable {
private static final Logger log = getLogger(PresenceService.class);
private final ShardManager shardManager;
private final Configuration configuration;
private final Statistic statistic;
+ /**
+ * Constructs a PresenceService with the specified shard manager, configuration, and statistic.
+ *
+ * @param shardManager the shard manager
+ * @param configuration the configuration
+ * @param statistic the statistic
+ */
public PresenceService(ShardManager shardManager, Configuration configuration, Statistic statistic) {
this.shardManager = shardManager;
this.configuration = configuration;
this.statistic = statistic;
}
+ /**
+ * Starts the presence service if it is active in the configuration.
+ *
+ * @param shardManager the shard manager
+ * @param configuration the configuration
+ * @param statistic the statistic
+ * @param executorService the scheduled executor service
+ */
public static void start(ShardManager shardManager, Configuration configuration, Statistic statistic, ScheduledExecutorService executorService) {
var presenceService = new PresenceService(shardManager, configuration, statistic);
if (configuration.presence().isActive()) {
@@ -37,12 +55,18 @@ public static void start(ShardManager shardManager, Configuration configuration,
}
}
+ /**
+ * Runs the presence service, refreshing the presence if it is active.
+ */
@Override
public void run() {
if (!configuration.presence().isActive()) return;
refresh();
}
+ /**
+ * Refreshes the bot's presence based on the current configuration and statistics.
+ */
private void refresh() {
var replacements = statistic.getSystemStatistic().replacements();
var currentPresence = configuration.presence().randomStatus();
diff --git a/src/main/java/de/chojo/repbot/service/RepBotCachePolicy.java b/src/main/java/de/chojo/repbot/service/RepBotCachePolicy.java
index b30a26a52..9536ba991 100644
--- a/src/main/java/de/chojo/repbot/service/RepBotCachePolicy.java
+++ b/src/main/java/de/chojo/repbot/service/RepBotCachePolicy.java
@@ -17,22 +17,44 @@
import java.util.HashSet;
import java.util.Set;
+/**
+ * Custom cache policy for managing member caching in the bot.
+ */
public class RepBotCachePolicy implements MemberCachePolicy, Runnable {
+ /**
+ * Duration for which members are cached, in minutes.
+ */
public static final int CACHE_DURATION = 30;
private final HashMap seen = new HashMap<>();
private final Scan scan;
-
private final Roles roles;
+ /**
+ * Constructs a RepBotCachePolicy with the specified scan and roles handlers.
+ *
+ * @param scan the scan handler
+ * @param roles the roles handler
+ */
public RepBotCachePolicy(Scan scan, Roles roles) {
this.scan = scan;
this.roles = roles;
}
+ /**
+ * Marks a member as seen at the current time.
+ *
+ * @param member the member to mark as seen
+ */
public void seen(Member member) {
seen.put(member.getIdLong(), Instant.now());
}
+ /**
+ * Determines whether a member should be cached based on various conditions.
+ *
+ * @param member the member to check
+ * @return true if the member should be cached, false otherwise
+ */
@Override
public boolean cacheMember(@NotNull Member member) {
if (MemberCachePolicy.VOICE.cacheMember(member)) {
@@ -68,11 +90,17 @@ public boolean cacheMember(@NotNull Member member) {
return false;
}
+ /**
+ * Runs the cache cleaning process.
+ */
@Override
public void run() {
clean();
}
+ /**
+ * Cleans the cache by removing members that have not been seen recently.
+ */
public synchronized void clean() {
Set remove = new HashSet<>();
var oldest = oldest();
@@ -84,6 +112,11 @@ public synchronized void clean() {
remove.forEach(seen::remove);
}
+ /**
+ * Returns the oldest time that a member can be seen and still be cached.
+ *
+ * @return the oldest acceptable time
+ */
private Instant oldest() {
return Instant.now().minus(CACHE_DURATION, ChronoUnit.MINUTES);
}
diff --git a/src/main/java/de/chojo/repbot/statistic/ReplacementProvider.java b/src/main/java/de/chojo/repbot/statistic/ReplacementProvider.java
index 21c95a43f..754f0f937 100644
--- a/src/main/java/de/chojo/repbot/statistic/ReplacementProvider.java
+++ b/src/main/java/de/chojo/repbot/statistic/ReplacementProvider.java
@@ -9,7 +9,15 @@
import java.util.List;
+/**
+ * Functional interface for providing a list of replacements.
+ */
@FunctionalInterface
public interface ReplacementProvider {
+ /**
+ * Returns a list of replacements.
+ *
+ * @return a list of {@link Replacement} objects
+ */
List replacements();
}
diff --git a/src/main/java/de/chojo/repbot/statistic/display/GlobalInfoStatisticDisplay.java b/src/main/java/de/chojo/repbot/statistic/display/GlobalInfoStatisticDisplay.java
index 89273d95b..2d3d44ac9 100644
--- a/src/main/java/de/chojo/repbot/statistic/display/GlobalInfoStatisticDisplay.java
+++ b/src/main/java/de/chojo/repbot/statistic/display/GlobalInfoStatisticDisplay.java
@@ -10,10 +10,20 @@
import de.chojo.repbot.statistic.element.GlobalShardStatistic;
import net.dv8tion.jda.api.EmbedBuilder;
+/**
+ * Represents a display for global information statistics.
+ *
+ * @param globalShardStatistic the global shard statistics
+ * @param dataStatistic the data statistics
+ */
public record GlobalInfoStatisticDisplay(GlobalShardStatistic globalShardStatistic,
DataStatistic dataStatistic) implements EmbedDisplay {
-
+ /**
+ * Appends the global information statistics to the provided embed builder.
+ *
+ * @param embedBuilder the embed builder to append the statistics to
+ */
@Override
public void appendTo(EmbedBuilder embedBuilder) {
embedBuilder.addField("Global Info",
diff --git a/src/main/java/de/chojo/repbot/statistic/element/DataStatistic.java b/src/main/java/de/chojo/repbot/statistic/element/DataStatistic.java
index 9f5ee482d..0135864c1 100644
--- a/src/main/java/de/chojo/repbot/statistic/element/DataStatistic.java
+++ b/src/main/java/de/chojo/repbot/statistic/element/DataStatistic.java
@@ -10,6 +10,9 @@
import java.util.List;
+/**
+ * Class representing data statistics for the application.
+ */
public class DataStatistic implements ReplacementProvider {
private final int guilds;
private final int activeGuilds;
@@ -20,10 +23,25 @@ public class DataStatistic implements ReplacementProvider {
private final int weeklyRep;
private final int weeklyAvgRep;
+ /**
+ * Constructs a DataStatistic instance with default values.
+ */
public DataStatistic() {
this(0, 0, 0, 0, 0, 0, 0, 0);
}
+ /**
+ * Constructs a DataStatistic instance with the specified values.
+ *
+ * @param guilds the number of guilds
+ * @param activeGuilds the number of active guilds
+ * @param activeChannel the number of active channels
+ * @param channel the number of channels
+ * @param totalRep the total reputation
+ * @param todayRep the reputation for today
+ * @param weeklyRep the weekly reputation
+ * @param weeklyAvgRep the weekly average reputation
+ */
public DataStatistic(int guilds, int activeGuilds, int activeChannel, int channel, int totalRep, int todayRep, int weeklyRep, int weeklyAvgRep) {
this.guilds = guilds;
this.activeGuilds = activeGuilds;
@@ -35,38 +53,83 @@ public DataStatistic(int guilds, int activeGuilds, int activeChannel, int channe
this.weeklyAvgRep = weeklyAvgRep;
}
+ /**
+ * Returns the number of guilds.
+ *
+ * @return the number of guilds
+ */
public int guilds() {
return guilds;
}
+ /**
+ * Returns the number of channels.
+ *
+ * @return the number of channels
+ */
public int channel() {
return channel;
}
+ /**
+ * Returns the total reputation.
+ *
+ * @return the total reputation
+ */
public int totalRep() {
return totalRep;
}
+ /**
+ * Returns the reputation for today.
+ *
+ * @return the reputation for today
+ */
public int today() {
return todayRep;
}
+ /**
+ * Returns the weekly reputation.
+ *
+ * @return the weekly reputation
+ */
public int weeklyRep() {
return weeklyRep;
}
+ /**
+ * Returns the weekly average reputation.
+ *
+ * @return the weekly average reputation
+ */
public int weeklyAvgRep() {
return weeklyAvgRep;
}
+ /**
+ * Returns the number of active guilds.
+ *
+ * @return the number of active guilds
+ */
public int activeGuilds() {
return activeGuilds;
}
+ /**
+ * Returns the number of active channels.
+ *
+ * @return the number of active channels
+ */
public int activeChannel() {
return activeChannel;
}
+ /**
+ * Returns a list of replacements for localization.
+ *
+ * @return a list of {@link Replacement} objects
+ */
@Override
public List replacements() {
return List.of(Replacement.create("guild_count", guilds), Replacement.create("channel_count", channel),
diff --git a/src/main/java/de/chojo/repbot/statistic/element/GlobalShardStatistic.java b/src/main/java/de/chojo/repbot/statistic/element/GlobalShardStatistic.java
index 225e279db..8c3cfa66e 100644
--- a/src/main/java/de/chojo/repbot/statistic/element/GlobalShardStatistic.java
+++ b/src/main/java/de/chojo/repbot/statistic/element/GlobalShardStatistic.java
@@ -11,19 +11,36 @@
import java.util.Collections;
import java.util.List;
+/**
+ * Class representing global shard statistics.
+ */
public class GlobalShardStatistic implements ReplacementProvider {
private final long analyzedMessages;
+ /**
+ * Constructs a new GlobalShardStatistic instance.
+ *
+ * @param shardStatistics a list of ShardStatistic instances
+ */
public GlobalShardStatistic(List shardStatistics) {
analyzedMessages = shardStatistics.stream()
.map(ShardStatistic::analyzedMessages).reduce(0L, Long::sum);
}
+ /**
+ * Retrieves the total number of analyzed messages.
+ *
+ * @return the total number of analyzed messages
+ */
public long analyzedMessages() {
return analyzedMessages;
}
-
+ /**
+ * Provides a list of replacements for localization.
+ *
+ * @return a list of Replacement instances
+ */
@Override
public List replacements() {
return Collections.singletonList(Replacement.create("analyzed_messages", analyzedMessages));
diff --git a/src/main/java/de/chojo/repbot/statistic/element/ProcessStatistics.java b/src/main/java/de/chojo/repbot/statistic/element/ProcessStatistics.java
index 670631b53..8ced92f4a 100644
--- a/src/main/java/de/chojo/repbot/statistic/element/ProcessStatistics.java
+++ b/src/main/java/de/chojo/repbot/statistic/element/ProcessStatistics.java
@@ -15,12 +15,26 @@
import java.time.temporal.ChronoUnit;
import java.util.List;
+/**
+ * Represents the statistics of the current process, including memory usage and thread count.
+ *
+ * @param total the total memory available to the process
+ * @param used the memory currently used by the process
+ * @param free the free memory available to the process
+ * @param max the maximum memory available to the process
+ * @param threads the number of active threads in the process
+ */
public record ProcessStatistics(long total, long used, long free, long max,
long threads) implements ReplacementProvider, EmbedDisplay {
private static final int MB = 1024 * 1024;
private static final Instant START = Instant.now();
+ /**
+ * Creates a new instance of ProcessStatistics with the current process information.
+ *
+ * @return a new ProcessStatistics instance
+ */
public static ProcessStatistics create() {
var instance = Runtime.getRuntime();
var total = instance.totalMemory() / MB;
@@ -31,10 +45,20 @@ public static ProcessStatistics create() {
return new ProcessStatistics(total, free, used, max, Thread.activeCount());
}
+ /**
+ * Gets the uptime of the process in milliseconds.
+ *
+ * @return the uptime of the process in milliseconds
+ */
public long uptime() {
return START.until(Instant.now(), ChronoUnit.MILLIS);
}
+ /**
+ * Provides a list of replacements for localization.
+ *
+ * @return a list of replacements
+ */
@Override
public List replacements() {
return List.of(Replacement.create("total_mem", total), Replacement.create("used_mem", used),
@@ -42,6 +66,11 @@ public List replacements() {
Replacement.create("threads", threads));
}
+ /**
+ * Appends the process statistics to the provided EmbedBuilder.
+ *
+ * @param embedBuilder the EmbedBuilder to append the statistics to
+ */
@Override
public void appendTo(EmbedBuilder embedBuilder) {
embedBuilder.addField("Process Info",
diff --git a/src/main/java/de/chojo/repbot/util/Colors.java b/src/main/java/de/chojo/repbot/util/Colors.java
index 46b55d7e3..5a0edcb6b 100644
--- a/src/main/java/de/chojo/repbot/util/Colors.java
+++ b/src/main/java/de/chojo/repbot/util/Colors.java
@@ -20,21 +20,69 @@ private Colors() {
*/
@SuppressWarnings("unused")
public static final class Pastel {
+ /**
+ * Light red pastel color.
+ */
public static final Color LIGHT_RED = new Color(235, 145, 145);
+ /**
+ * Red pastel color.
+ */
public static final Color RED = new Color(245, 93, 93);
+ /**
+ * Dark red pastel color.
+ */
public static final Color DARK_RED = new Color(168, 69, 69);
+ /**
+ * Orange pastel color.
+ */
public static final Color ORANGE = new Color(237, 156, 85);
+ /**
+ * Yellow pastel color.
+ */
public static final Color YELLOW = new Color(237, 221, 104);
+ /**
+ * Light green pastel color.
+ */
public static final Color LIGHT_GREEN = new Color(188, 242, 141);
+ /**
+ * Green pastel color.
+ */
public static final Color GREEN = new Color(137, 237, 123);
+ /**
+ * Dark green pastel color.
+ */
public static final Color DARK_GREEN = new Color(83, 158, 73);
+ /**
+ * Aqua pastel color.
+ */
public static final Color AQUA = new Color(183, 247, 247);
+ /**
+ * Light blue pastel color.
+ */
public static final Color LIGHT_BLUE = new Color(132, 204, 240);
+ /**
+ * Blue pastel color.
+ */
public static final Color BLUE = new Color(132, 161, 240);
+ /**
+ * Dark blue pastel color.
+ */
public static final Color DARK_BLUE = new Color(85, 106, 163);
+ /**
+ * Purple pastel color.
+ */
public static final Color PURPLE = new Color(189, 110, 204);
+ /**
+ * Dark pink pastel color.
+ */
public static final Color DARK_PINK = new Color(179, 57, 130);
+ /**
+ * Pink pastel color.
+ */
public static final Color PINK = new Color(201, 103, 177);
+ /**
+ * Light pink pastel color.
+ */
public static final Color LIGHT_PINK = new Color(209, 138, 192);
private Pastel() {
@@ -47,21 +95,69 @@ private Pastel() {
*/
@SuppressWarnings("unused")
public static final class Strong {
+ /**
+ * Light red strong color.
+ */
public static final Color LIGHT_RED = new Color(255, 97, 97);
+ /**
+ * Red strong color.
+ */
public static final Color RED = new Color(255, 0, 0);
+ /**
+ * Dark red strong color.
+ */
public static final Color DARK_RED = new Color(176, 0, 0);
+ /**
+ * Orange strong color.
+ */
public static final Color ORANGE = new Color(255, 132, 0);
+ /**
+ * Yellow strong color.
+ */
public static final Color YELLOW = new Color(255, 255, 0);
+ /**
+ * Light green strong color.
+ */
public static final Color LIGHT_GREEN = new Color(74, 255, 95);
+ /**
+ * Green strong color.
+ */
public static final Color GREEN = new Color(0, 255, 30);
+ /**
+ * Dark green strong color.
+ */
public static final Color DARK_GREEN = new Color(0, 181, 21);
+ /**
+ * Aqua strong color.
+ */
public static final Color AQUA = new Color(0, 255, 255);
+ /**
+ * Light blue strong color.
+ */
public static final Color LIGHT_BLUE = new Color(77, 184, 255);
+ /**
+ * Blue strong color.
+ */
public static final Color BLUE = new Color(0, 0, 255);
+ /**
+ * Dark blue strong color.
+ */
public static final Color DARK_BLUE = new Color(0, 0, 191);
+ /**
+ * Purple strong color.
+ */
public static final Color PURPLE = new Color(187, 0, 255);
+ /**
+ * Dark pink strong color.
+ */
public static final Color DARK_PINK = new Color(219, 0, 102);
+ /**
+ * Pink strong color.
+ */
public static final Color PINK = new Color(255, 0, 132);
+ /**
+ * Light pink strong color.
+ */
public static final Color LIGHT_PINK = new Color(255, 117, 198);
private Strong() {
diff --git a/src/main/java/de/chojo/repbot/util/EmojiDebug.java b/src/main/java/de/chojo/repbot/util/EmojiDebug.java
index dfa28e9b0..4fcee7121 100644
--- a/src/main/java/de/chojo/repbot/util/EmojiDebug.java
+++ b/src/main/java/de/chojo/repbot/util/EmojiDebug.java
@@ -5,17 +5,59 @@
*/
package de.chojo.repbot.util;
+/**
+ * Utility class for emoji debug symbols.
+ */
public final class EmojiDebug {
+ /**
+ * Indicates that a thank word was found.
+ */
public static final String FOUND_THANKWORD = "👀";
+
+ /**
+ * Indicates that only a cooldown is active.
+ */
public static final String ONLY_COOLDOWN = "💤";
+
+ /**
+ * Indicates that the context is empty.
+ */
public static final String EMPTY_CONTEXT = "🔍";
+
+ /**
+ * Indicates that the target is not in the context.
+ */
public static final String TARGET_NOT_IN_CONTEXT = "❓";
+
+ /**
+ * Indicates that the donor is not in the context.
+ */
public static final String DONOR_NOT_IN_CONTEXT = "❔";
+
+ /**
+ * Indicates that the context is too old.
+ */
public static final String TOO_OLD = "🕛";
+
+ /**
+ * Indicates that a prompt was made.
+ */
public static final String PROMPTED = "🗨";
+
+ /**
+ * Indicates that the receiver limit was reached.
+ */
public static final String RECEIVER_LIMIT = "✋";
+
+ /**
+ * Indicates that the donor limit was reached.
+ */
public static final String DONOR_LIMIT = "🤲";
+ /**
+ * Private constructor to prevent instantiation.
+ * Throws an UnsupportedOperationException if called.
+ */
private EmojiDebug() {
throw new UnsupportedOperationException("This is a utility class.");
}
diff --git a/src/main/java/de/chojo/repbot/util/FilterUtil.java b/src/main/java/de/chojo/repbot/util/FilterUtil.java
index ccf1e6247..c3bf5d246 100644
--- a/src/main/java/de/chojo/repbot/util/FilterUtil.java
+++ b/src/main/java/de/chojo/repbot/util/FilterUtil.java
@@ -12,22 +12,36 @@
import java.util.List;
import java.util.stream.Collectors;
+/**
+ * Utility class for filtering text channels in a guild based on permissions.
+ */
public final class FilterUtil {
+ /**
+ * Private constructor to prevent instantiation.
+ * Throws an UnsupportedOperationException if called.
+ */
private FilterUtil() {
throw new UnsupportedOperationException("This is a utility class.");
}
/**
- * Get all channel where the bot user can write and read.
+ * Retrieves all text channels in the guild where the bot user has both read and write permissions.
*
- * @param guild guild
- * @return list of accessable text channel
+ * @param guild the guild to filter channels from
+ * @return a list of accessible text channels
*/
public static List getAccessableTextChannel(Guild guild) {
return filterChannelByPermission(guild, Permission.VIEW_CHANNEL, Permission.MESSAGE_SEND);
}
+ /**
+ * Filters the text channels in the guild based on the specified permissions.
+ *
+ * @param guild the guild to filter channels from
+ * @param permissions the permissions to check for each channel
+ * @return a list of text channels that the bot user has the specified permissions for
+ */
public static List filterChannelByPermission(Guild guild, Permission... permissions) {
var self = guild.getSelfMember();
return guild.getTextChannels().stream().filter(textChannel -> self.hasPermission(textChannel, permissions))
diff --git a/src/main/java/de/chojo/repbot/util/Guilds.java b/src/main/java/de/chojo/repbot/util/Guilds.java
index a493c2ab8..d3f9d8553 100644
--- a/src/main/java/de/chojo/repbot/util/Guilds.java
+++ b/src/main/java/de/chojo/repbot/util/Guilds.java
@@ -7,11 +7,25 @@
import net.dv8tion.jda.api.entities.Guild;
+/**
+ * Utility class for guild-related operations.
+ */
public final class Guilds {
+
+ /**
+ * Private constructor to prevent instantiation.
+ * Throws an UnsupportedOperationException if called.
+ */
private Guilds() {
throw new UnsupportedOperationException("This is a utility class.");
}
+ /**
+ * Generates a pretty name for the guild, including its name and ID.
+ *
+ * @param guild the Guild instance
+ * @return a formatted string containing the guild's name and ID
+ */
public static String prettyName(Guild guild) {
return String.format("%s (%s)", guild.getName(), guild.getIdLong());
}
diff --git a/src/main/java/de/chojo/repbot/util/LogNotify.java b/src/main/java/de/chojo/repbot/util/LogNotify.java
index e44da93f8..1293efb4b 100644
--- a/src/main/java/de/chojo/repbot/util/LogNotify.java
+++ b/src/main/java/de/chojo/repbot/util/LogNotify.java
@@ -9,24 +9,38 @@
import org.slf4j.Marker;
import org.slf4j.MarkerFactory;
+/**
+ * Utility class for creating and managing log markers.
+ */
public final class LogNotify {
/**
- * Will be send to error-log channel.
+ * Marker for notifications to be sent to the error-log channel.
*/
public static final Marker NOTIFY_ADMIN = createMarker("NOTIFY_ADMIN");
/**
- * Will be sent to status-log.
+ * Marker for notifications to be sent to the status-log.
*/
public static final Marker STATUS = createMarker("STATUS");
/**
- * Currently unused.
+ * Marker currently unused.
*/
public static final Marker DISCORD = createMarker("DISCORD");
+ /**
+ * Private constructor to prevent instantiation.
+ * Throws an UnsupportedOperationException if called.
+ */
private LogNotify() {
throw new UnsupportedOperationException("This is a utility class.");
}
+ /**
+ * Creates a new marker with the specified name and optional child markers.
+ *
+ * @param name the name of the marker
+ * @param children optional child markers to add to the created marker
+ * @return the created marker
+ */
private static Marker createMarker(@NotNull String name, @NotNull Marker... children) {
var marker = MarkerFactory.getMarker(name);
for (var child : children) {
diff --git a/src/main/java/de/chojo/repbot/util/Messages.java b/src/main/java/de/chojo/repbot/util/Messages.java
index ac141db96..f4ea6e908 100644
--- a/src/main/java/de/chojo/repbot/util/Messages.java
+++ b/src/main/java/de/chojo/repbot/util/Messages.java
@@ -18,13 +18,26 @@
import static org.slf4j.LoggerFactory.getLogger;
+/**
+ * Utility class for handling message reactions.
+ */
public final class Messages {
private static final Logger log = getLogger(Messages.class);
+ /**
+ * Private constructor to prevent instantiation.
+ */
private Messages() {
throw new UnsupportedOperationException("This is a utility class.");
}
+ /**
+ * Adds a reaction to a message based on the settings.
+ *
+ * @param message the message to add a reaction to
+ * @param refMessage an optional reference message to also add the reaction to
+ * @param settings the settings containing the reaction information
+ */
public static void markMessage(Message message, @Nullable Message refMessage, Settings settings) {
var reaction = settings.thanking().reactions().mainReaction();
if (settings.thanking().reactions().reactionIsEmote()) {
@@ -38,6 +51,12 @@ public static void markMessage(Message message, @Nullable Message refMessage, Se
}
}
+ /**
+ * Adds an emoji reaction to a message.
+ *
+ * @param message the message to add a reaction to
+ * @param emote the emoji to add as a reaction
+ */
public static void markMessage(Message message, Emoji emote) {
if (PermissionUtil.checkPermission(message.getGuildChannel().getPermissionContainer(), message.getGuild()
.getSelfMember(), Permission.MESSAGE_ADD_REACTION)) {
@@ -45,6 +64,12 @@ public static void markMessage(Message message, Emoji emote) {
}
}
+ /**
+ * Adds a Unicode emoji reaction to a message.
+ *
+ * @param message the message to add a reaction to
+ * @param emoji the Unicode emoji to add as a reaction
+ */
public static void markMessage(Message message, String emoji) {
if (PermissionUtil.checkPermission(message.getGuildChannel().getPermissionContainer(), message.getGuild()
.getSelfMember(), Permission.MESSAGE_ADD_REACTION)) {
@@ -52,6 +77,11 @@ public static void markMessage(Message message, String emoji) {
}
}
+ /**
+ * Handles the reaction addition action, ignoring specific error responses.
+ *
+ * @param action the RestAction to handle
+ */
private static void handleMark(RestAction action) {
action.queue(RestAction.getDefaultSuccess(),
ErrorResponseException.ignore(
diff --git a/src/main/java/de/chojo/repbot/util/PermissionErrorHandler.java b/src/main/java/de/chojo/repbot/util/PermissionErrorHandler.java
index 787760c47..937ba7045 100644
--- a/src/main/java/de/chojo/repbot/util/PermissionErrorHandler.java
+++ b/src/main/java/de/chojo/repbot/util/PermissionErrorHandler.java
@@ -18,11 +18,22 @@
import net.dv8tion.jda.api.sharding.ShardManager;
import net.dv8tion.jda.internal.utils.PermissionUtil;
+/**
+ * Utility class for handling permission errors.
+ */
public final class PermissionErrorHandler {
private PermissionErrorHandler() {
throw new UnsupportedOperationException("This is a utility class.");
}
+ /**
+ * Handles an InsufficientPermissionException by sending a permission error message to the appropriate channel.
+ *
+ * @param permissionException the exception to handle
+ * @param shardManager the shard manager
+ * @param localizer the localization context
+ * @param configuration the configuration
+ */
public static void handle(InsufficientPermissionException permissionException, ShardManager shardManager,
LocalizationContext localizer, Configuration configuration) {
var permission = permissionException.getPermission();
@@ -32,6 +43,14 @@ public static void handle(InsufficientPermissionException permissionException, S
sendPermissionError(channel, permission, localizer, configuration);
}
+ /**
+ * Handles an InsufficientPermissionException by sending a permission error message to the appropriate channel.
+ *
+ * @param permissionException the exception to handle
+ * @param guild the guild
+ * @param localizer the localization context
+ * @param configuration the configuration
+ */
public static void handle(InsufficientPermissionException permissionException, Guild guild, LocalizationContext localizer,
Configuration configuration) {
var permission = permissionException.getPermission();
@@ -40,6 +59,14 @@ public static void handle(InsufficientPermissionException permissionException, G
sendPermissionError(channel, permission, localizer, configuration);
}
+ /**
+ * Handles an InsufficientPermissionException by sending a permission error message to the appropriate channel.
+ *
+ * @param permissionException the exception to handle
+ * @param channel the channel
+ * @param localizer the localization context
+ * @param configuration the configuration
+ */
public static void handle(InsufficientPermissionException permissionException, GuildMessageChannel channel,
LocalizationContext localizer, Configuration configuration) {
var permission = permissionException.getPermission();
@@ -47,6 +74,14 @@ public static void handle(InsufficientPermissionException permissionException, G
sendPermissionError(channel, permission, localizer, configuration);
}
+ /**
+ * Sends a permission error message to the specified channel.
+ *
+ * @param channel the channel to send the message to
+ * @param permission the missing permission
+ * @param localizer the localization context
+ * @param configuration the configuration
+ */
public static void sendPermissionError(GuildMessageChannel channel, Permission permission, LocalizationContext localizer,
Configuration configuration) {
var guild = channel.getGuild();
@@ -92,6 +127,13 @@ public static void assertPermissions(GuildMessageChannel channel, Permission...
}
}
+ /**
+ * Assert that the user has permissions.
+ *
+ * @param guild guild to check
+ * @param permissions permissions to check
+ * @throws InsufficientPermissionException when the bot user doesnt have a permission
+ */
public static void assertPermissions(Guild guild, Permission... permissions) throws InsufficientPermissionException {
var self = guild.getSelfMember();
for (var permission : permissions) {
diff --git a/src/main/java/de/chojo/repbot/web/Api.java b/src/main/java/de/chojo/repbot/web/Api.java
index 240671572..28798e2ec 100644
--- a/src/main/java/de/chojo/repbot/web/Api.java
+++ b/src/main/java/de/chojo/repbot/web/Api.java
@@ -6,7 +6,7 @@
package de.chojo.repbot.web;
import de.chojo.repbot.dao.provider.Metrics;
-import de.chojo.repbot.web.erros.ApiException;
+import de.chojo.repbot.web.error.ApiException;
import de.chojo.repbot.web.routes.v1.MetricsRoute;
import io.javalin.Javalin;
import org.slf4j.Logger;
@@ -15,16 +15,28 @@
import static io.javalin.apibuilder.ApiBuilder.path;
import static org.slf4j.LoggerFactory.getLogger;
+/**
+ * The Api class initializes and configures the Javalin web server with routes and exception handling.
+ */
public class Api {
private static final Logger log = getLogger(Api.class);
private final Javalin javalin;
private final MetricsRoute metricsRoute;
+ /**
+ * Constructs an Api instance with the specified Javalin instance and Metrics provider.
+ *
+ * @param javalin the Javalin instance to be used
+ * @param metrics the Metrics provider
+ */
public Api(Javalin javalin, Metrics metrics) {
this.javalin = javalin;
metricsRoute = new MetricsRoute(metrics);
}
+ /**
+ * Initializes the API by setting up exception handling and routes.
+ */
public void init() {
javalin.exception(ApiException.class, (err, ctx) -> ctx.result(err.getMessage()).status(err.status()));
javalin.routes(() -> {
diff --git a/src/main/java/de/chojo/repbot/web/error/ApiException.java b/src/main/java/de/chojo/repbot/web/error/ApiException.java
index c6bfea804..1d0f1d96c 100644
--- a/src/main/java/de/chojo/repbot/web/error/ApiException.java
+++ b/src/main/java/de/chojo/repbot/web/error/ApiException.java
@@ -3,18 +3,32 @@
*
* Copyright (C) RainbowDashLabs and Contributor
*/
-package de.chojo.repbot.web.erros;
+package de.chojo.repbot.web.error;
import io.javalin.http.HttpCode;
+/**
+ * Custom exception class for API errors.
+ */
public class ApiException extends RuntimeException {
private final HttpCode status;
+ /**
+ * Constructs a new ApiException with the specified HTTP status code and message.
+ *
+ * @param status the HTTP status code
+ * @param message the detail message
+ */
public ApiException(HttpCode status, String message) {
super(message);
this.status = status;
}
+ /**
+ * Returns the HTTP status code associated with this exception.
+ *
+ * @return the HTTP status code
+ */
public HttpCode status() {
return status;
}
diff --git a/src/main/java/de/chojo/repbot/web/routes/RoutesBuilder.java b/src/main/java/de/chojo/repbot/web/routes/RoutesBuilder.java
index e30445112..996493b59 100644
--- a/src/main/java/de/chojo/repbot/web/routes/RoutesBuilder.java
+++ b/src/main/java/de/chojo/repbot/web/routes/RoutesBuilder.java
@@ -5,6 +5,12 @@
*/
package de.chojo.repbot.web.routes;
+/**
+ * Interface for building routes.
+ */
public interface RoutesBuilder {
+ /**
+ * Builds the routes.
+ */
void buildRoutes();
}
diff --git a/src/main/java/de/chojo/repbot/web/routes/v1/MetricsHolder.java b/src/main/java/de/chojo/repbot/web/routes/v1/MetricsHolder.java
index e8e52cf53..d6c350a73 100644
--- a/src/main/java/de/chojo/repbot/web/routes/v1/MetricsHolder.java
+++ b/src/main/java/de/chojo/repbot/web/routes/v1/MetricsHolder.java
@@ -6,7 +6,7 @@
package de.chojo.repbot.web.routes.v1;
import de.chojo.repbot.dao.provider.Metrics;
-import de.chojo.repbot.web.erros.ApiException;
+import de.chojo.repbot.web.error.ApiException;
import de.chojo.repbot.web.routes.RoutesBuilder;
import de.chojo.repbot.web.routes.v1.metrics.MetricCache;
import io.javalin.http.Context;
@@ -17,20 +17,40 @@
import static org.slf4j.LoggerFactory.getLogger;
+/**
+ * Abstract class for handling metrics-related routes.
+ */
public abstract class MetricsHolder implements RoutesBuilder {
private static final Logger log = getLogger(MetricsHolder.class);
private final MetricCache cache;
private final Metrics metrics;
+ /**
+ * Constructs a new MetricsHolder with the specified cache and metrics.
+ *
+ * @param cache the metric cache
+ * @param metrics the metrics provider
+ */
public MetricsHolder(MetricCache cache, Metrics metrics) {
this.cache = cache;
this.metrics = metrics;
}
+ /**
+ * Returns the metrics provider.
+ *
+ * @return the metrics provider
+ */
public Metrics metrics() {
return metrics;
}
+ /**
+ * Writes an image to the HTTP context.
+ *
+ * @param ctx the HTTP context
+ * @param png the image data in PNG format
+ */
protected void writeImage(Context ctx, byte[] png) {
ctx.header("Content-Disposition", "filename=\"stats.png\"");
ctx.header("X-Content-Type-Options", "nosniff");
@@ -39,6 +59,14 @@ protected void writeImage(Context ctx, byte[] png) {
ctx.result(png).status(HttpStatus.OK_200);
}
+ /**
+ * Retrieves and validates the offset parameter from the context.
+ *
+ * @param context the HTTP context
+ * @param max the maximum allowed value for the offset
+ * @return the validated offset value
+ * @throws ApiException if the offset is not a valid number or is out of range
+ */
protected int offset(Context context, int max) {
var param = context.pathParam("offset");
try {
@@ -50,6 +78,14 @@ protected int offset(Context context, int max) {
}
}
+ /**
+ * Retrieves and validates the count parameter from the context.
+ *
+ * @param context the HTTP context
+ * @param max the maximum allowed value for the count
+ * @return the validated count value
+ * @throws ApiException if the count is not a valid number or is out of range
+ */
protected int count(Context context, int max) {
var param = context.pathParam("count");
try {
@@ -61,6 +97,14 @@ protected int count(Context context, int max) {
}
}
+ /**
+ * Asserts that a value is within the specified range.
+ *
+ * @param value the value to check
+ * @param min the minimum allowed value
+ * @param max the maximum allowed value
+ * @throws ApiException if the value is out of range
+ */
private void assertSize(int value, int min, int max) {
if (value < min) {
throw new ApiException(HttpCode.BAD_REQUEST, String.format("Value %s is too small. Min: %s", value, min));
@@ -70,6 +114,12 @@ private void assertSize(int value, int min, int max) {
}
}
+ /**
+ * Wraps a handler with caching functionality.
+ *
+ * @param handler the handler to wrap
+ * @return the wrapped handler
+ */
public Handler cache(Handler handler) {
return cache.cache(handler);
}
diff --git a/src/main/java/de/chojo/repbot/web/routes/v1/MetricsRoute.java b/src/main/java/de/chojo/repbot/web/routes/v1/MetricsRoute.java
index e9e44ddfa..bcd54d282 100644
--- a/src/main/java/de/chojo/repbot/web/routes/v1/MetricsRoute.java
+++ b/src/main/java/de/chojo/repbot/web/routes/v1/MetricsRoute.java
@@ -14,18 +14,56 @@
import de.chojo.repbot.web.routes.v1.metrics.Users;
import io.swagger.v3.oas.models.parameters.Parameter;
+/**
+ * Class for building and managing metric-related routes.
+ */
public class MetricsRoute implements RoutesBuilder {
+ /**
+ * Maximum offset for hours.
+ */
public static final int MAX_HOUR_OFFSET = 336;
+
+ /**
+ * Maximum offset for days.
+ */
public static final int MAX_DAY_OFFSET = 60;
+
+ /**
+ * Maximum offset for weeks.
+ */
public static final int MAX_WEEK_OFFSET = 52;
+
+ /**
+ * Maximum offset for months.
+ */
public static final int MAX_MONTH_OFFSET = 24;
+
+ /**
+ * Maximum offset for years.
+ */
public static final int MAX_YEAR_OFFSET = 2;
+ /**
+ * Maximum count for hours.
+ */
public static final int MAX_HOURS = 120;
+
+ /**
+ * Maximum count for days.
+ */
public static final int MAX_DAYS = 120;
+
+ /**
+ * Maximum count for weeks.
+ */
public static final int MAX_WEEKS = 104;
+
+ /**
+ * Maximum count for months.
+ */
public static final int MAX_MONTH = 48;
+
private final Reputation reputation;
private final Commands commands;
private final Messages messages;
@@ -33,6 +71,11 @@ public class MetricsRoute implements RoutesBuilder {
private final MetricCache cache;
private final Service service;
+ /**
+ * Constructs a new MetricsRoute with the specified metrics provider.
+ *
+ * @param metrics the metrics provider
+ */
public MetricsRoute(de.chojo.repbot.dao.provider.Metrics metrics) {
cache = new MetricCache();
reputation = new Reputation(metrics, cache);
@@ -42,7 +85,9 @@ public MetricsRoute(de.chojo.repbot.dao.provider.Metrics metrics) {
service = new Service(metrics, cache);
}
-
+ /**
+ * Builds the routes for the metrics.
+ */
@Override
public void buildRoutes() {
cache.buildRoutes();
@@ -53,50 +98,115 @@ public void buildRoutes() {
service.buildRoutes();
}
+ /**
+ * Sets the documentation for the offset parameter.
+ *
+ * @param parameter the parameter to set the documentation for
+ * @param resolution the resolution of the offset
+ * @param maxValue the maximum value for the offset
+ */
private static void offsetDoc(Parameter parameter, String resolution, int maxValue) {
setParameter(parameter, "%s offset. 0 is current %s. Max value is %s".formatted(resolution, resolution.toLowerCase(), maxValue));
}
+ /**
+ * Sets the documentation for the day offset parameter.
+ *
+ * @param p the parameter to set the documentation for
+ */
public static void offsetDayDoc(Parameter p) {
offsetDoc(p, "Day", MAX_DAY_OFFSET);
}
+ /**
+ * Sets the documentation for the hour offset parameter.
+ *
+ * @param p the parameter to set the documentation for
+ */
public static void offsetHourDoc(Parameter p) {
offsetDoc(p, "Hour", MAX_HOUR_OFFSET);
}
+ /**
+ * Sets the documentation for the week offset parameter.
+ *
+ * @param p the parameter to set the documentation for
+ */
public static void offsetWeekDoc(Parameter p) {
offsetDoc(p, "Week", MAX_WEEK_OFFSET);
}
+ /**
+ * Sets the documentation for the month offset parameter.
+ *
+ * @param p the parameter to set the documentation for
+ */
public static void offsetMonthDoc(Parameter p) {
offsetDoc(p, "Month", MAX_MONTH_OFFSET);
}
+ /**
+ * Sets the documentation for the year offset parameter.
+ *
+ * @param p the parameter to set the documentation for
+ */
public static void offsetYearDoc(Parameter p) {
offsetDoc(p, "Year", MAX_YEAR_OFFSET);
}
+ /**
+ * Sets the documentation for the count parameter.
+ *
+ * @param parameter the parameter to set the documentation for
+ * @param resolution the resolution of the count
+ * @param maxValue the maximum value for the count
+ */
private static void countDoc(Parameter parameter, String resolution, int maxValue) {
setParameter(parameter, "%s count. Amount of previously %s in the chart. Max value is %s".formatted(resolution, resolution.toLowerCase(), maxValue));
}
+ /**
+ * Sets the documentation for the hour count parameter.
+ *
+ * @param p the parameter to set the documentation for
+ */
public static void countHourDoc(Parameter p) {
countDoc(p, "Hours", MAX_HOURS);
}
+ /**
+ * Sets the documentation for the day count parameter.
+ *
+ * @param p the parameter to set the documentation for
+ */
public static void countDayDoc(Parameter p) {
countDoc(p, "Days", MAX_DAYS);
}
+ /**
+ * Sets the documentation for the week count parameter.
+ *
+ * @param p the parameter to set the documentation for
+ */
public static void countWeekDoc(Parameter p) {
countDoc(p, "Weeks", MAX_WEEKS);
}
+ /**
+ * Sets the documentation for the month count parameter.
+ *
+ * @param p the parameter to set the documentation for
+ */
public static void countMonthDoc(Parameter p) {
countDoc(p, "Months", MAX_MONTH);
}
+ /**
+ * Sets the description for the parameter.
+ *
+ * @param p the parameter to set the description for
+ * @param description the description to set
+ */
private static void setParameter(Parameter p, String description) {
p.setDescription(description);
}
diff --git a/src/main/java/de/chojo/repbot/web/routes/v1/metrics/Commands.java b/src/main/java/de/chojo/repbot/web/routes/v1/metrics/Commands.java
index f218ee4a7..e17dde0aa 100644
--- a/src/main/java/de/chojo/repbot/web/routes/v1/metrics/Commands.java
+++ b/src/main/java/de/chojo/repbot/web/routes/v1/metrics/Commands.java
@@ -20,11 +20,25 @@
import static io.javalin.apibuilder.ApiBuilder.get;
import static io.javalin.apibuilder.ApiBuilder.path;
+/**
+ * Handles the metrics related to commands.
+ */
public class Commands extends MetricsHolder {
+ /**
+ * Constructs a Commands instance with the specified metrics and cache.
+ *
+ * @param metrics the metrics provider
+ * @param cache the metric cache
+ */
public Commands(Metrics metrics, MetricCache cache) {
super(cache, metrics);
}
+ /**
+ * Handles the request for command usage statistics for a week.
+ *
+ * @param ctx the context of the request
+ */
public void usageWeek(Context ctx) {
var stats = metrics().commands().week(offset(ctx, MAX_WEEK_OFFSET));
if ("application/json".equals(ctx.header("Accept"))) {
@@ -34,6 +48,11 @@ public void usageWeek(Context ctx) {
}
}
+ /**
+ * Handles the request for command usage statistics for a month.
+ *
+ * @param ctx the context of the request
+ */
public void usageMonth(Context ctx) {
var stats = metrics().commands().month(offset(ctx, MAX_MONTH_OFFSET));
if ("application/json".equals(ctx.header("Accept"))) {
@@ -43,6 +62,11 @@ public void usageMonth(Context ctx) {
}
}
+ /**
+ * Handles the request for the count of commands executed per week.
+ *
+ * @param ctx the context of the request
+ */
public void countWeek(Context ctx) {
var stats = metrics().commands().week(offset(ctx, MAX_WEEK_OFFSET), count(ctx, MAX_WEEKS));
if ("application/json".equals(ctx.header("Accept"))) {
@@ -52,6 +76,11 @@ public void countWeek(Context ctx) {
}
}
+ /**
+ * Handles the request for the count of commands executed per month.
+ *
+ * @param ctx the context of the request
+ */
public void countMonth(Context ctx) {
var stats = metrics().commands().month(offset(ctx, MAX_MONTH_OFFSET), count(ctx, MAX_MONTH));
if ("application/json".equals(ctx.header("Accept"))) {
@@ -61,13 +90,16 @@ public void countMonth(Context ctx) {
}
}
+ /**
+ * Builds the routes for the commands metrics.
+ */
@Override
public void buildRoutes() {
path("commands", () -> {
path("count", () -> {
get("week/{offset}/{count}", OpenApiBuilder.documented(OpenApiBuilder.document()
.operation(op -> {
- op.summary("Get the amount of exectued commands per week.");
+ op.summary("Get the amount of executed commands per week.");
})
.result("200", byte[].class, "image/png")
.result("200", CommandsStatistic.class, "application/json")
@@ -76,7 +108,7 @@ public void buildRoutes() {
cache(this::countWeek)));
get("month/{offset}/{count}", OpenApiBuilder.documented(OpenApiBuilder.document()
.operation(op -> {
- op.summary("Get the amount of exectued commands per month.");
+ op.summary("Get the amount of executed commands per month.");
})
.result("200", byte[].class, "image/png")
.result("200", CommandsStatistic.class, "application/json")
diff --git a/src/main/java/de/chojo/repbot/web/routes/v1/metrics/Messages.java b/src/main/java/de/chojo/repbot/web/routes/v1/metrics/Messages.java
index 75ba93105..9cd767bf9 100644
--- a/src/main/java/de/chojo/repbot/web/routes/v1/metrics/Messages.java
+++ b/src/main/java/de/chojo/repbot/web/routes/v1/metrics/Messages.java
@@ -23,11 +23,25 @@
import static io.javalin.apibuilder.ApiBuilder.get;
import static io.javalin.apibuilder.ApiBuilder.path;
+/**
+ * Handles the metrics related to messages.
+ */
public class Messages extends MetricsHolder {
+ /**
+ * Constructs a new Messages handler.
+ *
+ * @param metrics the Metrics provider
+ * @param cache the MetricCache
+ */
public Messages(Metrics metrics, MetricCache cache) {
super(cache, metrics);
}
+ /**
+ * Handles the request to get the count of messages analyzed per hour.
+ *
+ * @param ctx the Javalin context
+ */
public void countHour(Context ctx) {
var stats = metrics().messages().hour(offset(ctx, MAX_HOUR_OFFSET), count(ctx, MAX_HOURS));
if ("application/json".equals(ctx.header("Accept"))) {
@@ -37,6 +51,11 @@ public void countHour(Context ctx) {
}
}
+ /**
+ * Handles the request to get the count of messages analyzed per day.
+ *
+ * @param ctx the Javalin context
+ */
public void countDay(Context ctx) {
var stats = metrics().messages().day(offset(ctx, MAX_DAY_OFFSET), count(ctx, MAX_DAYS));
if ("application/json".equals(ctx.header("Accept"))) {
@@ -46,6 +65,11 @@ public void countDay(Context ctx) {
}
}
+ /**
+ * Handles the request to get the count of messages analyzed per week.
+ *
+ * @param ctx the Javalin context
+ */
public void countWeek(Context ctx) {
var stats = metrics().messages().week(offset(ctx, MAX_WEEK_OFFSET), count(ctx, MAX_WEEKS));
if ("application/json".equals(ctx.header("Accept"))) {
@@ -55,6 +79,11 @@ public void countWeek(Context ctx) {
}
}
+ /**
+ * Handles the request to get the count of messages analyzed per month.
+ *
+ * @param ctx the Javalin context
+ */
public void countMonth(Context ctx) {
var stats = metrics().messages().month(offset(ctx, MAX_MONTH_OFFSET), count(ctx, MAX_MONTH));
if ("application/json".equals(ctx.header("Accept"))) {
@@ -64,6 +93,11 @@ public void countMonth(Context ctx) {
}
}
+ /**
+ * Handles the request to get the total count of messages analyzed per day.
+ *
+ * @param ctx the Javalin context
+ */
public void totalDay(Context ctx) {
var stats = metrics().messages().totalDay(offset(ctx, MAX_DAY_OFFSET), count(ctx, MAX_DAYS));
if ("application/json".equals(ctx.header("Accept"))) {
@@ -73,6 +107,11 @@ public void totalDay(Context ctx) {
}
}
+ /**
+ * Handles the request to get the total count of messages analyzed per week.
+ *
+ * @param ctx the Javalin context
+ */
public void totalWeek(Context ctx) {
var stats = metrics().messages().totalWeek(offset(ctx, MAX_WEEK_OFFSET), count(ctx, MAX_WEEKS));
if ("application/json".equals(ctx.header("Accept"))) {
@@ -82,6 +121,11 @@ public void totalWeek(Context ctx) {
}
}
+ /**
+ * Handles the request to get the total count of messages analyzed per month.
+ *
+ * @param ctx the Javalin context
+ */
public void totalMonth(Context ctx) {
var stats = metrics().messages().totalMonth(offset(ctx, MAX_MONTH_OFFSET), count(ctx, MAX_MONTH));
if ("application/json".equals(ctx.header("Accept"))) {
@@ -91,6 +135,9 @@ public void totalMonth(Context ctx) {
}
}
+ /**
+ * Builds the routes for message metrics.
+ */
@Override
public void buildRoutes() {
path("messages", () -> {
diff --git a/src/main/java/de/chojo/repbot/web/routes/v1/metrics/MetricCache.java b/src/main/java/de/chojo/repbot/web/routes/v1/metrics/MetricCache.java
index 04fc7e9cb..39a528bee 100644
--- a/src/main/java/de/chojo/repbot/web/routes/v1/metrics/MetricCache.java
+++ b/src/main/java/de/chojo/repbot/web/routes/v1/metrics/MetricCache.java
@@ -22,6 +22,9 @@
import static io.javalin.apibuilder.ApiBuilder.after;
import static org.slf4j.LoggerFactory.getLogger;
+/**
+ * Handles caching of metric responses to improve performance and reduce load.
+ */
public class MetricCache implements RoutesBuilder {
private static final Logger log = getLogger(MetricCache.class);
private final RateLimiter rateLimiter;
@@ -30,10 +33,19 @@ public class MetricCache implements RoutesBuilder {
.maximumSize(100)
.build();
+ /**
+ * Constructs a MetricCache with a rate limiter.
+ */
public MetricCache() {
rateLimiter = new RateLimiter(TimeUnit.MINUTES);
}
+ /**
+ * Returns a handler that caches the response of the given handler.
+ *
+ * @param supplier the handler whose response should be cached
+ * @return a handler that caches the response
+ */
public Handler cache(Handler supplier) {
return ctx -> {
var cacheKey = new CacheKey(ctx);
@@ -50,6 +62,9 @@ public Handler cache(Handler supplier) {
};
}
+ /**
+ * Builds the routes for caching metric responses.
+ */
@Override
public void buildRoutes() {
after(ctx -> {
@@ -61,6 +76,9 @@ public void buildRoutes() {
});
}
+ /**
+ * Represents a cached response.
+ */
private static class ResponseCache {
String route;
String accept;
@@ -69,6 +87,11 @@ private static class ResponseCache {
int status;
byte[] body;
+ /**
+ * Constructs a ResponseCache from the given context.
+ *
+ * @param ctx the context
+ */
ResponseCache(Context ctx) {
route = ctx.path();
accept = ctx.header("Accept");
@@ -83,6 +106,11 @@ private static class ResponseCache {
}
}
+ /**
+ * Applies the cached response to the given context.
+ *
+ * @param ctx the context
+ */
void apply(Context ctx) {
ctx.status(status);
for (var header : header.entrySet()) {
@@ -94,10 +122,18 @@ void apply(Context ctx) {
}
}
+ /**
+ * Represents a key for caching responses.
+ */
private static class CacheKey {
String route;
String accept;
+ /**
+ * Constructs a CacheKey from the given context.
+ *
+ * @param ctx the context
+ */
CacheKey(Context ctx) {
route = ctx.path();
accept = ctx.header("Accept");