diff --git a/pom.xml b/pom.xml index 598e03d..59b234a 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.rappytv.globaltags GlobalTagsJava - 1.1.9 + 1.2.0 GlobalTagsJava A wrapper for the GlobalTagsAPI @@ -35,8 +35,8 @@ - 17 - 17 + 11 + 11 UTF-8 diff --git a/src/main/java/com/rappytv/globaltags/wrapper/GlobalTagsAPI.java b/src/main/java/com/rappytv/globaltags/wrapper/GlobalTagsAPI.java index e499c4b..f4f3265 100644 --- a/src/main/java/com/rappytv/globaltags/wrapper/GlobalTagsAPI.java +++ b/src/main/java/com/rappytv/globaltags/wrapper/GlobalTagsAPI.java @@ -33,7 +33,7 @@ public abstract class GlobalTagsAPI { */ @NotNull public Urls getUrls() { - return urls; + return this.urls; } /** @@ -76,7 +76,7 @@ public String getLanguageCode() { */ @NotNull public PlayerInfo.Cache getCache() { - return cache; + return this.cache; } /** @@ -85,7 +85,7 @@ public PlayerInfo.Cache getCache() { */ @NotNull public ApiHandler getApiHandler() { - return apiHandler; + return this.apiHandler; } /** @@ -108,9 +108,9 @@ public ApiHandler getApiHandler() { */ @NotNull public String getAuthorizationHeader() { - String auth = getAuthorization(); + String auth = this.getAuthorization(); if(auth == null) return ""; - return String.format("%s %s", getAuthType().getId(), auth); + return String.format("%s %s", this.getAuthType().getId(), auth); } /** @@ -149,7 +149,7 @@ public Agent(@NotNull String agent, @NotNull String agentVersion, @Nullable Stri */ @NotNull public String getAgent() { - return agent; + return this.agent; } /** @@ -158,7 +158,7 @@ public String getAgent() { */ @NotNull public String getAgentVersion() { - return agentVersion; + return this.agentVersion; } /** @@ -167,7 +167,7 @@ public String getAgentVersion() { */ @Nullable public String getMinecraftVersion() { - return minecraftVersion; + return this.minecraftVersion; } @Override @@ -176,7 +176,7 @@ public String getMinecraftVersion() { "%s v%s%s", this.agent, this.agentVersion, - minecraftVersion != null ? " - " + minecraftVersion : "" + this.minecraftVersion != null ? " - " + this.minecraftVersion : "" ); } } diff --git a/src/main/java/com/rappytv/globaltags/wrapper/enums/AuthProvider.java b/src/main/java/com/rappytv/globaltags/wrapper/enums/AuthProvider.java index bf1f8e5..f3477d8 100644 --- a/src/main/java/com/rappytv/globaltags/wrapper/enums/AuthProvider.java +++ b/src/main/java/com/rappytv/globaltags/wrapper/enums/AuthProvider.java @@ -28,6 +28,6 @@ public enum AuthProvider { * @return The internal identifier of the authentication provider */ public String getId() { - return id; + return this.id; } } diff --git a/src/main/java/com/rappytv/globaltags/wrapper/enums/ReferralLeaderboardType.java b/src/main/java/com/rappytv/globaltags/wrapper/enums/ReferralLeaderboardType.java new file mode 100644 index 0000000..9876538 --- /dev/null +++ b/src/main/java/com/rappytv/globaltags/wrapper/enums/ReferralLeaderboardType.java @@ -0,0 +1,15 @@ +package com.rappytv.globaltags.wrapper.enums; + +/** + * An enum for the type of the referral leaderboard + */ +public enum ReferralLeaderboardType { + /** + * The total number of referrals + */ + TOTAL, + /** + * The number of referrals in the current month + */ + CURRENT_MONTH +} diff --git a/src/main/java/com/rappytv/globaltags/wrapper/http/ApiHandler.java b/src/main/java/com/rappytv/globaltags/wrapper/http/ApiHandler.java index 1c7295b..370ff8b 100644 --- a/src/main/java/com/rappytv/globaltags/wrapper/http/ApiHandler.java +++ b/src/main/java/com/rappytv/globaltags/wrapper/http/ApiHandler.java @@ -4,11 +4,9 @@ import com.rappytv.globaltags.wrapper.enums.ConnectionType; import com.rappytv.globaltags.wrapper.enums.GlobalIcon; import com.rappytv.globaltags.wrapper.enums.GlobalPosition; +import com.rappytv.globaltags.wrapper.enums.ReferralLeaderboardType; import com.rappytv.globaltags.wrapper.http.schemas.*; -import com.rappytv.globaltags.wrapper.model.ApiInfo; -import com.rappytv.globaltags.wrapper.model.PlayerInfo; -import com.rappytv.globaltags.wrapper.model.PlayerNote; -import com.rappytv.globaltags.wrapper.model.TagHistoryEntry; +import com.rappytv.globaltags.wrapper.model.*; import java.util.*; import java.util.function.Consumer; @@ -44,16 +42,63 @@ public ApiHandler(GlobalTagsAPI api) { */ public void getApiInfo(Consumer> consumer) { new ApiRequest<>( - api, + this.api, "GET", Routes.getApiInfo(), ApiInfo.class ).sendRequestAsync((response) -> { - if(!response.successful()) { - consumer.accept(new ApiResponse<>(false, null, response.error())); + if(!response.isSuccessful()) { + consumer.accept(new ApiResponse<>(false, null, response.getError())); return; } - consumer.accept(new ApiResponse<>(true, response.data(), null)); + consumer.accept(new ApiResponse<>(true, response.getData(), null)); + }); + } + + /** + * A request to get the current referral leaderboards + * + * @param consumer The action to be executed on response. + */ + public void getReferralLeaderboards(Consumer>>> consumer) { + new ApiRequest<>( + this.api, + "GET", + Routes.getReferralLeaderboards(), + ReferralLeaderboardsSchema.class + ).sendRequestAsync((response) -> { + if (!response.isSuccessful()) { + consumer.accept(new ApiResponse<>(false, null, response.getError())); + return; + } + ReferralLeaderboardsSchema schemas = response.getData(); + Map> leaderboards = new HashMap<>(); + List totalEntries = new ArrayList<>(); + List currentMonthEntries = new ArrayList<>(); + try { + for (int i = 0; i < schemas.totalLeaderboard.length; i++) { + ReferralLeaderboardsSchema.ReferralLeaderboardEntrySchema entry = schemas.totalLeaderboard[i]; + totalEntries.add(new ReferralLeaderboardEntry( + i + 1, + UUID.fromString(entry.uuid), + entry.totalReferrals, + entry.currentMonthReferrals + )); + } + for (int i = 0; i < schemas.currentMonthLeaderboard.length; i++) { + ReferralLeaderboardsSchema.ReferralLeaderboardEntrySchema entry = schemas.currentMonthLeaderboard[i]; + currentMonthEntries.add(new ReferralLeaderboardEntry( + i + 1, + UUID.fromString(entry.uuid), + entry.totalReferrals, + entry.currentMonthReferrals + )); + } + } catch (IllegalArgumentException ignored) { + } + leaderboards.put(ReferralLeaderboardType.TOTAL, totalEntries); + leaderboards.put(ReferralLeaderboardType.CURRENT_MONTH, currentMonthEntries); + consumer.accept(new ApiResponse<>(true, leaderboards, null)); }); } @@ -63,7 +108,7 @@ public void getApiInfo(Consumer> consumer) { * @param consumer The action to be executed on response. */ public void getInfo(Consumer>> consumer) { - getInfo(api.getClientUUID(), consumer); + this.getInfo(this.api.getClientUUID(), consumer); } /** @@ -74,25 +119,24 @@ public void getInfo(Consumer>> consumer) { */ public void getInfo(UUID uuid, Consumer>> consumer) { new ApiRequest<>( - api, + this.api, "GET", Routes.player(uuid), PlayerInfoSchema.class ).sendRequestAsync((response) -> { - if(!response.successful()) { - consumer.accept(new ApiResponse<>(false, null, response.error())); + if(!response.isSuccessful()) { + consumer.accept(new ApiResponse<>(false, null, response.getError())); return; } - PlayerInfoSchema body = response.data(); + PlayerInfoSchema body = response.getData(); consumer.accept(new ApiResponse<>( true, new PlayerInfo<>( - api, + this.api, uuid, body.tag, body.position, body.icon, - body.referred, body.referrals, body.roles, body.permissions, @@ -109,7 +153,7 @@ public void getInfo(UUID uuid, Consumer>> consumer) { * @param consumer The action to be executed on response. */ public void getTagHistory(Consumer>> consumer) { - getTagHistory(api.getClientUUID(), consumer); + this.getTagHistory(this.api.getClientUUID(), consumer); } /** @@ -120,18 +164,18 @@ public void getTagHistory(Consumer>> consumer) */ public void getTagHistory(UUID uuid, Consumer>> consumer) { new ApiRequest<>( - api, + this.api, "GET", Routes.tagHistory(uuid), TagHistoryEntry[].class ).sendRequestAsync((response) -> { - if(!response.successful()) { - consumer.accept(new ApiResponse<>(false, null, response.error())); + if(!response.isSuccessful()) { + consumer.accept(new ApiResponse<>(false, null, response.getError())); return; } consumer.accept(new ApiResponse<>( true, - Arrays.asList(response.data()), + Arrays.asList(response.getData()), null )); }); @@ -144,7 +188,7 @@ public void getTagHistory(UUID uuid, Consumer> * @param consumer The action to be executed on response. */ public void setTag(String tag, Consumer> consumer) { - setTag(api.getClientUUID(), tag, consumer); + this.setTag(this.api.getClientUUID(), tag, consumer); } /** @@ -156,18 +200,18 @@ public void setTag(String tag, Consumer> consumer) { */ public void setTag(UUID uuid, String tag, Consumer> consumer) { new ApiRequest<>( - api, + this.api, "POST", Routes.player(uuid), Map.of("tag", tag), MessageSchema.class ).sendRequestAsync((response) -> { - if(!response.successful()) { - consumer.accept(new ApiResponse<>(false, null, response.error())); + if(!response.isSuccessful()) { + consumer.accept(new ApiResponse<>(false, null, response.getError())); return; } - api.getCache().renew(uuid, (info) -> - consumer.accept(new ApiResponse<>(true, response.data().message, null)) + this.api.getCache().renew(uuid, (info) -> + consumer.accept(new ApiResponse<>(true, response.getData().message, null)) ); }); } @@ -179,7 +223,7 @@ public void setTag(UUID uuid, String tag, Consumer> consumer * @param consumer The action to be executed on response. */ public void setPosition(GlobalPosition position, Consumer> consumer) { - setPosition(api.getClientUUID(), position, consumer); + this.setPosition(this.api.getClientUUID(), position, consumer); } /** @@ -191,18 +235,18 @@ public void setPosition(GlobalPosition position, Consumer> c */ public void setPosition(UUID uuid, GlobalPosition position, Consumer> consumer) { new ApiRequest<>( - api, + this.api, "POST", Routes.setPosition(uuid), Map.of("position", position.name()), MessageSchema.class ).sendRequestAsync((response) -> { - if(!response.successful()) { - consumer.accept(new ApiResponse<>(false, null, response.error())); + if(!response.isSuccessful()) { + consumer.accept(new ApiResponse<>(false, null, response.getError())); return; } - api.getCache().renew(uuid, (info) -> - consumer.accept(new ApiResponse<>(true, response.data().message, null)) + this.api.getCache().renew(uuid, (info) -> + consumer.accept(new ApiResponse<>(true, response.getData().message, null)) ); }); } @@ -214,7 +258,7 @@ public void setPosition(UUID uuid, GlobalPosition position, Consumer> consumer) { - setIcon(api.getClientUUID(), icon, consumer); + this.setIcon(this.api.getClientUUID(), icon, consumer); } /** @@ -226,18 +270,18 @@ public void setIcon(GlobalIcon icon, Consumer> consumer) { */ public void setIcon(UUID uuid, GlobalIcon icon, Consumer> consumer) { new ApiRequest<>( - api, + this.api, "POST", Routes.setIcon(uuid), Map.of("icon", icon.name()), MessageSchema.class ).sendRequestAsync((response) -> { - if(!response.successful()) { - consumer.accept(new ApiResponse<>(false, null, response.error())); + if(!response.isSuccessful()) { + consumer.accept(new ApiResponse<>(false, null, response.getError())); return; } - api.getCache().renew(uuid, (info) -> - consumer.accept(new ApiResponse<>(true, response.data().message, null)) + this.api.getCache().renew(uuid, (info) -> + consumer.accept(new ApiResponse<>(true, response.getData().message, null)) ); }); } @@ -248,7 +292,7 @@ public void setIcon(UUID uuid, GlobalIcon icon, Consumer> co * @param consumer The action to be executed on response. */ public void resetTag(Consumer> consumer) { - resetTag(api.getClientUUID(), consumer); + this.resetTag(this.api.getClientUUID(), consumer); } /** @@ -259,18 +303,18 @@ public void resetTag(Consumer> consumer) { */ public void resetTag(UUID uuid, Consumer> consumer) { new ApiRequest<>( - api, + this.api, "DELETE", Routes.player(uuid), emptyBody, MessageSchema.class ).sendRequestAsync((response) -> { - if(!response.successful()) { - consumer.accept(new ApiResponse<>(false, null, response.error())); + if(!response.isSuccessful()) { + consumer.accept(new ApiResponse<>(false, null, response.getError())); return; } - api.getCache().renew(uuid, (info) -> - consumer.accept(new ApiResponse<>(true, response.data().message, null)) + this.api.getCache().renew(uuid, (info) -> + consumer.accept(new ApiResponse<>(true, response.getData().message, null)) ); }); } @@ -283,17 +327,17 @@ public void resetTag(UUID uuid, Consumer> consumer) { */ public void watchPlayer(UUID uuid, Consumer> consumer) { new ApiRequest<>( - api, + this.api, "POST", Routes.watchPlayer(uuid), emptyBody, MessageSchema.class ).sendRequestAsync((response) -> { - if(!response.successful()) { - consumer.accept(new ApiResponse<>(false, null, response.error())); + if(!response.isSuccessful()) { + consumer.accept(new ApiResponse<>(false, null, response.getError())); return; } - consumer.accept(new ApiResponse<>(true, response.data().message, null)); + consumer.accept(new ApiResponse<>(true, response.getData().message, null)); }); } @@ -305,17 +349,17 @@ public void watchPlayer(UUID uuid, Consumer> consumer) { */ public void unwatchPlayer(UUID uuid, Consumer> consumer) { new ApiRequest<>( - api, + this.api, "POST", Routes.unwatchPlayer(uuid), emptyBody, MessageSchema.class ).sendRequestAsync((response) -> { - if(!response.successful()) { - consumer.accept(new ApiResponse<>(false, null, response.error())); + if(!response.isSuccessful()) { + consumer.accept(new ApiResponse<>(false, null, response.getError())); return; } - consumer.accept(new ApiResponse<>(true, response.data().message, null)); + consumer.accept(new ApiResponse<>(true, response.getData().message, null)); }); } @@ -327,17 +371,17 @@ public void unwatchPlayer(UUID uuid, Consumer> consumer) { */ public void referPlayer(UUID uuid, Consumer> consumer) { new ApiRequest<>( - api, + this.api, "POST", Routes.referPlayer(uuid), emptyBody, MessageSchema.class ).sendRequestAsync((response) -> { - if(!response.successful()) { - consumer.accept(new ApiResponse<>(false, null, response.error())); + if(!response.isSuccessful()) { + consumer.accept(new ApiResponse<>(false, null, response.getError())); return; } - consumer.accept(new ApiResponse<>(true, response.data().message, null)); + consumer.accept(new ApiResponse<>(true, response.getData().message, null)); }); } @@ -350,17 +394,17 @@ public void referPlayer(UUID uuid, Consumer> consumer) { */ public void reportPlayer(UUID uuid, String reason, Consumer> consumer) { new ApiRequest<>( - api, + this.api, "POST", Routes.reportPlayer(uuid), Map.of("reason", reason), MessageSchema.class ).sendRequestAsync((response) -> { - if(!response.successful()) { - consumer.accept(new ApiResponse<>(false, null, response.error())); + if(!response.isSuccessful()) { + consumer.accept(new ApiResponse<>(false, null, response.getError())); return; } - consumer.accept(new ApiResponse<>(true, response.data().message, null)); + consumer.accept(new ApiResponse<>(true, response.getData().message, null)); }); } @@ -373,18 +417,18 @@ public void reportPlayer(UUID uuid, String reason, Consumer> */ public void banPlayer(UUID uuid, String reason, Consumer> consumer) { new ApiRequest<>( - api, + this.api, "POST", Routes.ban(uuid), Map.of("reason", reason), MessageSchema.class ).sendRequestAsync((response) -> { - if(!response.successful()) { - consumer.accept(new ApiResponse<>(false, null, response.error())); + if(!response.isSuccessful()) { + consumer.accept(new ApiResponse<>(false, null, response.getError())); return; } - api.getCache().renew(uuid, (info) -> - consumer.accept(new ApiResponse<>(true, response.data().message, null)) + this.api.getCache().renew(uuid, (info) -> + consumer.accept(new ApiResponse<>(true, response.getData().message, null)) ); }); } @@ -397,18 +441,18 @@ public void banPlayer(UUID uuid, String reason, Consumer> co */ public void unbanPlayer(UUID uuid, Consumer> consumer) { new ApiRequest<>( - api, + this.api, "DELETE", Routes.ban(uuid), emptyBody, MessageSchema.class ).sendRequestAsync((response) -> { - if(!response.successful()) { - consumer.accept(new ApiResponse<>(false, null, response.error())); + if(!response.isSuccessful()) { + consumer.accept(new ApiResponse<>(false, null, response.getError())); return; } - api.getCache().renew(uuid, (info) -> - consumer.accept(new ApiResponse<>(true, response.data().message, null)) + this.api.getCache().renew(uuid, (info) -> + consumer.accept(new ApiResponse<>(true, response.getData().message, null)) ); }); } @@ -423,18 +467,18 @@ public void unbanPlayer(UUID uuid, Consumer> consumer) { public void editBan(UUID uuid, PlayerInfo.Suspension suspension, Consumer> consumer) { Objects.requireNonNull(suspension.getReason(), "Reason must not be null"); new ApiRequest<>( - api, + this.api, "PUT", Routes.ban(uuid), Map.of("reason", suspension.getReason(), "appealable", suspension.isAppealable()), MessageSchema.class ).sendRequestAsync((response) -> { - if(!response.successful()) { - consumer.accept(new ApiResponse<>(false, null, response.error())); + if(!response.isSuccessful()) { + consumer.accept(new ApiResponse<>(false, null, response.getError())); return; } - api.getCache().renew(uuid, (info) -> - consumer.accept(new ApiResponse<>(true, response.data().message, null)) + this.api.getCache().renew(uuid, (info) -> + consumer.accept(new ApiResponse<>(true, response.getData().message, null)) ); }); } @@ -447,17 +491,17 @@ public void editBan(UUID uuid, PlayerInfo.Suspension suspension, Consumer> consumer) { new ApiRequest<>( - api, + this.api, "POST", - Routes.appealBan(api.getClientUUID()), + Routes.appealBan(this.api.getClientUUID()), Map.of("reason", reason), MessageSchema.class ).sendRequestAsync((response) -> { - if(!response.successful()) { - consumer.accept(new ApiResponse<>(false, null, response.error())); + if(!response.isSuccessful()) { + consumer.accept(new ApiResponse<>(false, null, response.getError())); return; } - consumer.accept(new ApiResponse<>(true, response.data().message, null)); + consumer.accept(new ApiResponse<>(true, response.getData().message, null)); }); } @@ -468,17 +512,17 @@ public void appealBan(String reason, Consumer> consumer) { */ public void linkDiscord(Consumer> consumer) { new ApiRequest<>( - api, + this.api, "POST", - Routes.connection(api.getClientUUID(), ConnectionType.DISCORD), + Routes.connection(this.api.getClientUUID(), ConnectionType.DISCORD), emptyBody, VerificationCodeSchema.class ).sendRequestAsync((response) -> { - if(!response.successful()) { - consumer.accept(new ApiResponse<>(false, null, response.error())); + if(!response.isSuccessful()) { + consumer.accept(new ApiResponse<>(false, null, response.getError())); return; } - consumer.accept(new ApiResponse<>(true, response.data().code, null)); + consumer.accept(new ApiResponse<>(true, response.getData().code, null)); }); } @@ -489,18 +533,18 @@ public void linkDiscord(Consumer> consumer) { */ public void unlinkDiscord(Consumer> consumer) { new ApiRequest<>( - api, + this.api, "DELETE", - Routes.connection(api.getClientUUID(), ConnectionType.DISCORD), + Routes.connection(this.api.getClientUUID(), ConnectionType.DISCORD), emptyBody, MessageSchema.class ).sendRequestAsync((response) -> { - if(!response.successful()) { - consumer.accept(new ApiResponse<>(false, null, response.error())); + if(!response.isSuccessful()) { + consumer.accept(new ApiResponse<>(false, null, response.getError())); return; } - api.getCache().renewSelf((info) -> - consumer.accept(new ApiResponse<>(true, response.data().message, null)) + this.api.getCache().renewSelf((info) -> + consumer.accept(new ApiResponse<>(true, response.getData().message, null)) ); }); } @@ -513,17 +557,17 @@ public void unlinkDiscord(Consumer> consumer) { */ public void linkEmail(String email, Consumer> consumer) { new ApiRequest<>( - api, + this.api, "POST", - Routes.connection(api.getClientUUID(), ConnectionType.EMAIL), + Routes.connection(this.api.getClientUUID(), ConnectionType.EMAIL), Map.of("email", email), MessageSchema.class ).sendRequestAsync((response) -> { - if(!response.successful()) { - consumer.accept(new ApiResponse<>(false, null, response.error())); + if(!response.isSuccessful()) { + consumer.accept(new ApiResponse<>(false, null, response.getError())); return; } - consumer.accept(new ApiResponse<>(true, response.data().message, null)); + consumer.accept(new ApiResponse<>(true, response.getData().message, null)); }); } @@ -534,17 +578,17 @@ public void linkEmail(String email, Consumer> consumer) { */ public void unlinkEmail(Consumer> consumer) { new ApiRequest<>( - api, + this.api, "DELETE", - Routes.connection(api.getClientUUID(), ConnectionType.EMAIL), + Routes.connection(this.api.getClientUUID(), ConnectionType.EMAIL), emptyBody, MessageSchema.class ).sendRequestAsync((response) -> { - if(!response.successful()) { - consumer.accept(new ApiResponse<>(false, null, response.error())); + if(!response.isSuccessful()) { + consumer.accept(new ApiResponse<>(false, null, response.getError())); return; } - consumer.accept(new ApiResponse<>(true, response.data().message, null)); + consumer.accept(new ApiResponse<>(true, response.getData().message, null)); }); } @@ -556,17 +600,17 @@ public void unlinkEmail(Consumer> consumer) { */ public void verifyEmail(String code, Consumer> consumer) { new ApiRequest<>( - api, + this.api, "POST", - Routes.verifyEmail(api.getClientUUID(), code), + Routes.verifyEmail(this.api.getClientUUID(), code), emptyBody, MessageSchema.class ).sendRequestAsync((response) -> { - if(!response.successful()) { - consumer.accept(new ApiResponse<>(false, null, response.error())); + if(!response.isSuccessful()) { + consumer.accept(new ApiResponse<>(false, null, response.getError())); return; } - consumer.accept(new ApiResponse<>(true, response.data().message, null)); + consumer.accept(new ApiResponse<>(true, response.getData().message, null)); }); } @@ -576,7 +620,7 @@ public void verifyEmail(String code, Consumer> consumer) { * @param consumer The action to be executed on response. */ public void getNotes(Consumer>> consumer) { - getNotes(api.getClientUUID(), consumer); + this.getNotes(this.api.getClientUUID(), consumer); } /** @@ -587,18 +631,18 @@ public void getNotes(Consumer>> consumer) { */ public void getNotes(UUID uuid, Consumer>> consumer) { new ApiRequest<>( - api, + this.api, "GET", Routes.notes(uuid), emptyBody, NoteSchema[].class ).sendRequestAsync((response) -> { - if(!response.successful()) { - consumer.accept(new ApiResponse<>(false, null, response.error())); + if(!response.isSuccessful()) { + consumer.accept(new ApiResponse<>(false, null, response.getError())); return; } List notes = new ArrayList<>(); - for(NoteSchema note : response.data()) { + for(NoteSchema note : response.getData()) { notes.add(new PlayerNote( note.id, note.text, @@ -617,7 +661,7 @@ public void getNotes(UUID uuid, Consumer>> consumer * @param consumer The action to be executed on response. */ public void createNote(String note, Consumer> consumer) { - createNote(api.getClientUUID(), note, consumer); + this.createNote(this.api.getClientUUID(), note, consumer); } /** @@ -629,17 +673,17 @@ public void createNote(String note, Consumer> consumer) { */ public void createNote(UUID uuid, String note, Consumer> consumer) { new ApiRequest<>( - api, + this.api, "POST", Routes.notes(uuid), Map.of("note", note), MessageSchema.class ).sendRequestAsync((response) -> { - if(!response.successful()) { - consumer.accept(new ApiResponse<>(false, null, response.error())); + if(!response.isSuccessful()) { + consumer.accept(new ApiResponse<>(false, null, response.getError())); return; } - consumer.accept(new ApiResponse<>(true, response.data().message, null)); + consumer.accept(new ApiResponse<>(true, response.getData().message, null)); }); } @@ -650,7 +694,7 @@ public void createNote(UUID uuid, String note, Consumer> con * @param consumer The action to be executed on response. */ public void getNote(String noteId, Consumer> consumer) { - getNote(api.getClientUUID(), noteId, consumer); + this.getNote(this.api.getClientUUID(), noteId, consumer); } /** @@ -662,17 +706,17 @@ public void getNote(String noteId, Consumer> consumer) { */ public void getNote(UUID uuid, String noteId, Consumer> consumer) { new ApiRequest<>( - api, + this.api, "GET", Routes.note(uuid, noteId), emptyBody, NoteSchema.class ).sendRequestAsync((response) -> { - if(!response.successful()) { - consumer.accept(new ApiResponse<>(false, null, response.error())); + if(!response.isSuccessful()) { + consumer.accept(new ApiResponse<>(false, null, response.getError())); return; } - NoteSchema body = response.data(); + NoteSchema body = response.getData(); consumer.accept(new ApiResponse<>( false, new PlayerNote( @@ -693,7 +737,7 @@ public void getNote(UUID uuid, String noteId, Consumer> * @param consumer The action to be executed on response. */ public void deleteNote(String noteId, Consumer> consumer) { - deleteNote(api.getClientUUID(), noteId, consumer); + this.deleteNote(this.api.getClientUUID(), noteId, consumer); } /** @@ -705,26 +749,67 @@ public void deleteNote(String noteId, Consumer> consumer) { */ public void deleteNote(UUID uuid, String noteId, Consumer> consumer) { new ApiRequest<>( - api, + this.api, "DELETE", Routes.note(uuid, noteId), emptyBody, MessageSchema.class ).sendRequestAsync((response) -> { - if(!response.successful()) { - consumer.accept(new ApiResponse<>(false, null, response.error())); + if(!response.isSuccessful()) { + consumer.accept(new ApiResponse<>(false, null, response.getError())); return; } - consumer.accept(new ApiResponse<>(true, response.data().message, null)); + consumer.accept(new ApiResponse<>(true, response.getData().message, null)); }); } /** * An inline class containing response data for these requests - * @param successful If the request was successful - * @param data The data returned if available - * @param error The error returned if available - * @param The type of the returned data - */ - public record ApiResponse(boolean successful, T data, String error) {} + * @param The type of the data + */ + public static class ApiResponse { + + private final boolean successful; + private final T data; + private final String error; + + /** + * Constructs a new ApiResponse instance + * + * @param successful If the request was successful + * @param data The data returned if available + * @param error The error returned if available + */ + public ApiResponse(boolean successful, T data, String error) { + this.successful = successful; + this.data = data; + this.error = error; + } + + /** + * Checks if the request was successful + * + * @return If the request was successful + */ + public boolean isSuccessful() { + return this.successful; + } + + /** + * Gets the data returned if available + * + * @return the data if available + */ + public T getData() { + return this.data; + } + + /** + * Get the error returned if available + * @return an error if available + */ + public String getError() { + return this.error; + } + } } diff --git a/src/main/java/com/rappytv/globaltags/wrapper/http/ApiHandler.java~ b/src/main/java/com/rappytv/globaltags/wrapper/http/ApiHandler.java~ new file mode 100644 index 0000000..15d284a --- /dev/null +++ b/src/main/java/com/rappytv/globaltags/wrapper/http/ApiHandler.java~ @@ -0,0 +1,757 @@ +package com.rappytv.globaltags.wrapper.http; + +import com.rappytv.globaltags.wrapper.GlobalTagsAPI; +import com.rappytv.globaltags.wrapper.enums.ConnectionType; +import com.rappytv.globaltags.wrapper.enums.GlobalIcon; +import com.rappytv.globaltags.wrapper.enums.GlobalPosition; +import com.rappytv.globaltags.wrapper.http.schemas.*; +import com.rappytv.globaltags.wrapper.model.ApiInfo; +import com.rappytv.globaltags.wrapper.model.PlayerInfo; +import com.rappytv.globaltags.wrapper.model.PlayerNote; +import com.rappytv.globaltags.wrapper.model.TagHistoryEntry; + +import java.util.*; +import java.util.function.Consumer; + +/** + * A class containing all requests to the GlobalTagAPI + * + * @param The same as the T value of your {@link GlobalTagsAPI} instance. + */ +@SuppressWarnings("unused") +public class ApiHandler { + + /** + * See elysiajs/elysia#495 for more info. + */ + private static final Map emptyBody = Map.of("data", "placeholder data"); + + private final GlobalTagsAPI api; + + /** + * Instantiates a new ApiHandler + * + * @param api The corresponding api where it's being implemented + */ + public ApiHandler(GlobalTagsAPI api) { + this.api = api; + } + + /** + * A request to get the api version + * + * @param consumer The action to be executed on response. + */ + public void getApiInfo(Consumer> consumer) { + new ApiRequest<>( + api, + "GET", + Routes.getApiInfo(), + ApiInfo.class + ).sendRequestAsync((response) -> { + if(!response.successful()) { + consumer.accept(new ApiResponse<>(false, null, response.error())); + return; + } + consumer.accept(new ApiResponse<>(true, response.data(), null)); + }); + } + + /** + * A request to get the player info of {@link GlobalTagsAPI#getClientUUID()} + * + * @param consumer The action to be executed on response. + */ + public void getInfo(Consumer>> consumer) { + getInfo(api.getClientUUID(), consumer); + } + + /** + * A request to get the player info of a specific uuid + * + * @param uuid The uuid to get the info of + * @param consumer The action to be executed on response. + */ + public void getInfo(UUID uuid, Consumer>> consumer) { + new ApiRequest<>( + api, + "GET", + Routes.player(uuid), + PlayerInfoSchema.class + ).sendRequestAsync((response) -> { + if(!response.successful()) { + consumer.accept(new ApiResponse<>(false, null, response.error())); + return; + } + PlayerInfoSchema body = response.data(); + consumer.accept(new ApiResponse<>( + true, + new PlayerInfo<>( + api, + uuid, + body.tag, + body.position, + body.icon, + body.referred, + body.referrals, + body.roles, + body.permissions, + body.ban + ), + null + )); + }); + } + + /** + * A request to get the tag history of {@link GlobalTagsAPI#getClientUUID()} + * + * @param consumer The action to be executed on response. + */ + public void getTagHistory(Consumer>> consumer) { + getTagHistory(api.getClientUUID(), consumer); + } + + /** + * A request to get the tag history of a specific uuid + * + * @param uuid The uuid to get the tag history of + * @param consumer The action to be executed on response. + */ + public void getTagHistory(UUID uuid, Consumer>> consumer) { + new ApiRequest<>( + api, + "GET", + Routes.tagHistory(uuid), + TagHistoryEntry[].class + ).sendRequestAsync((response) -> { + if(!response.successful()) { + consumer.accept(new ApiResponse<>(false, null, response.error())); + return; + } + consumer.accept(new ApiResponse<>( + true, + Arrays.asList(response.data()), + null + )); + }); + } + + /** + * A request to update the tag of {@link GlobalTagsAPI#getClientUUID()} + * + * @param tag The new tag you want to set + * @param consumer The action to be executed on response. + */ + public void setTag(String tag, Consumer> consumer) { + setTag(api.getClientUUID(), tag, consumer); + } + + /** + * A request to update the tag of a specific uuid + * + * @param uuid The uuid you want to update the tag of + * @param tag The new tag you want to set + * @param consumer The action to be executed on response. + */ + public void setTag(UUID uuid, String tag, Consumer> consumer) { + new ApiRequest<>( + api, + "POST", + Routes.player(uuid), + Map.of("tag", tag), + MessageSchema.class + ).sendRequestAsync((response) -> { + if(!response.successful()) { + consumer.accept(new ApiResponse<>(false, null, response.error())); + return; + } + api.getCache().renew(uuid, (info) -> + consumer.accept(new ApiResponse<>(true, response.data().message, null)) + ); + }); + } + + /** + * A request to update the {@link GlobalPosition} of {@link GlobalTagsAPI#getClientUUID()} + * + * @param position The new position you want to set + * @param consumer The action to be executed on response. + */ + public void setPosition(GlobalPosition position, Consumer> consumer) { + setPosition(api.getClientUUID(), position, consumer); + } + + /** + * A request to update the {@link GlobalPosition} of a specific uuid + * + * @param uuid The uuid you want to update the position of + * @param position The new position you want to set + * @param consumer The action to be executed on response. + */ + public void setPosition(UUID uuid, GlobalPosition position, Consumer> consumer) { + new ApiRequest<>( + api, + "POST", + Routes.setPosition(uuid), + Map.of("position", position.name()), + MessageSchema.class + ).sendRequestAsync((response) -> { + if(!response.successful()) { + consumer.accept(new ApiResponse<>(false, null, response.error())); + return; + } + api.getCache().renew(uuid, (info) -> + consumer.accept(new ApiResponse<>(true, response.data().message, null)) + ); + }); + } + + /** + * A request to update the global icon of {@link GlobalTagsAPI#getClientUUID()} + * + * @param icon The new icon you want to set + * @param consumer The action to be executed on response. + */ + public void setIcon(GlobalIcon icon, Consumer> consumer) { + setIcon(api.getClientUUID(), icon, consumer); + } + + /** + * A request to update the global icon of a specific uuid + * + * @param uuid The uuid you want to update the icon of + * @param icon The new icon you want to set + * @param consumer The action to be executed on response. + */ + public void setIcon(UUID uuid, GlobalIcon icon, Consumer> consumer) { + new ApiRequest<>( + api, + "POST", + Routes.setIcon(uuid), + Map.of("icon", icon.name()), + MessageSchema.class + ).sendRequestAsync((response) -> { + if(!response.successful()) { + consumer.accept(new ApiResponse<>(false, null, response.error())); + return; + } + api.getCache().renew(uuid, (info) -> + consumer.accept(new ApiResponse<>(true, response.data().message, null)) + ); + }); + } + + /** + * A request to clear the tag of {@link GlobalTagsAPI#getClientUUID()} + * + * @param consumer The action to be executed on response. + */ + public void resetTag(Consumer> consumer) { + resetTag(api.getClientUUID(), consumer); + } + + /** + * A request to clear the tag of a specific uuid + * + * @param uuid The uuid you want to clear the tag of + * @param consumer The action to be executed on response. + */ + public void resetTag(UUID uuid, Consumer> consumer) { + new ApiRequest<>( + api, + "DELETE", + Routes.player(uuid), + emptyBody, + MessageSchema.class + ).sendRequestAsync((response) -> { + if(!response.successful()) { + consumer.accept(new ApiResponse<>(false, null, response.error())); + return; + } + api.getCache().renew(uuid, (info) -> + consumer.accept(new ApiResponse<>(true, response.data().message, null)) + ); + }); + } + + /** + * A request to add a player to the watchlist + * + * @param uuid The uuid you want to add to the watchlist + * @param consumer The action to be executed on response. + */ + public void watchPlayer(UUID uuid, Consumer> consumer) { + new ApiRequest<>( + api, + "POST", + Routes.watchPlayer(uuid), + emptyBody, + MessageSchema.class + ).sendRequestAsync((response) -> { + if(!response.successful()) { + consumer.accept(new ApiResponse<>(false, null, response.error())); + return; + } + consumer.accept(new ApiResponse<>(true, response.data().message, null)); + }); + } + + /** + * A request to remove a player from the watchlist + * + * @param uuid The uuid you want to remove from the watchlist + * @param consumer The action to be executed on response. + */ + public void unwatchPlayer(UUID uuid, Consumer> consumer) { + new ApiRequest<>( + api, + "POST", + Routes.unwatchPlayer(uuid), + emptyBody, + MessageSchema.class + ).sendRequestAsync((response) -> { + if(!response.successful()) { + consumer.accept(new ApiResponse<>(false, null, response.error())); + return; + } + consumer.accept(new ApiResponse<>(true, response.data().message, null)); + }); + } + + /** + * A request to mark a specific uuid as the inviter of {@link GlobalTagsAPI#getClientUUID()} + * + * @param uuid The uuid you want to mark as the inviter + * @param consumer The action to be executed on response. + */ + public void referPlayer(UUID uuid, Consumer> consumer) { + new ApiRequest<>( + api, + "POST", + Routes.referPlayer(uuid), + emptyBody, + MessageSchema.class + ).sendRequestAsync((response) -> { + if(!response.successful()) { + consumer.accept(new ApiResponse<>(false, null, response.error())); + return; + } + consumer.accept(new ApiResponse<>(true, response.data().message, null)); + }); + } + + /** + * A request to report a specific uuid + * + * @param uuid The uuid you want to report + * @param reason The reason why you want to report the uuid + * @param consumer The action to be executed on response. + */ + public void reportPlayer(UUID uuid, String reason, Consumer> consumer) { + new ApiRequest<>( + api, + "POST", + Routes.reportPlayer(uuid), + Map.of("reason", reason), + MessageSchema.class + ).sendRequestAsync((response) -> { + if(!response.successful()) { + consumer.accept(new ApiResponse<>(false, null, response.error())); + return; + } + consumer.accept(new ApiResponse<>(true, response.data().message, null)); + }); + } + + /** + * A request to ban a specific uuid + * + * @param uuid The uuid you want to ban + * @param reason The reason for the ban + * @param consumer The action to be executed on response. + */ + public void banPlayer(UUID uuid, String reason, Consumer> consumer) { + new ApiRequest<>( + api, + "POST", + Routes.ban(uuid), + Map.of("reason", reason), + MessageSchema.class + ).sendRequestAsync((response) -> { + if(!response.successful()) { + consumer.accept(new ApiResponse<>(false, null, response.error())); + return; + } + api.getCache().renew(uuid, (info) -> + consumer.accept(new ApiResponse<>(true, response.data().message, null)) + ); + }); + } + + /** + * A request to unban a specific uuid + * + * @param uuid The uuid you want to unban + * @param consumer The action to be executed on response. + */ + public void unbanPlayer(UUID uuid, Consumer> consumer) { + new ApiRequest<>( + api, + "DELETE", + Routes.ban(uuid), + emptyBody, + MessageSchema.class + ).sendRequestAsync((response) -> { + if(!response.successful()) { + consumer.accept(new ApiResponse<>(false, null, response.error())); + return; + } + api.getCache().renew(uuid, (info) -> + consumer.accept(new ApiResponse<>(true, response.data().message, null)) + ); + }); + } + + /** + * A request to edit the ban of a specific uuid + * + * @param uuid The uuid you want to edit the ban of + * @param suspension The new {@link PlayerInfo.Suspension} object + * @param consumer The action to be executed on response. + */ + public void editBan(UUID uuid, PlayerInfo.Suspension suspension, Consumer> consumer) { + Objects.requireNonNull(suspension.getReason(), "Reason must not be null"); + new ApiRequest<>( + api, + "PUT", + Routes.ban(uuid), + Map.of("reason", suspension.getReason(), "appealable", suspension.isAppealable()), + MessageSchema.class + ).sendRequestAsync((response) -> { + if(!response.successful()) { + consumer.accept(new ApiResponse<>(false, null, response.error())); + return; + } + api.getCache().renew(uuid, (info) -> + consumer.accept(new ApiResponse<>(true, response.data().message, null)) + ); + }); + } + + /** + * A request to appeal the ban of {@link GlobalTagsAPI#getClientUUID()} + * + * @param reason The reason why {@link GlobalTagsAPI#getClientUUID()} should be unbanned + * @param consumer The action to be executed on response. + */ + public void appealBan(String reason, Consumer> consumer) { + new ApiRequest<>( + api, + "POST", + Routes.appealBan(api.getClientUUID()), + Map.of("reason", reason), + MessageSchema.class + ).sendRequestAsync((response) -> { + if(!response.successful()) { + consumer.accept(new ApiResponse<>(false, null, response.error())); + return; + } + consumer.accept(new ApiResponse<>(true, response.data().message, null)); + }); + } + + /** + * A request to get the discord linking code of {@link GlobalTagsAPI#getClientUUID()}. Implementation Note: Please don't show the code; Only copy it to the clipboard + * + * @param consumer The action to be executed on response. + */ + public void linkDiscord(Consumer> consumer) { + new ApiRequest<>( + api, + "POST", + Routes.connection(api.getClientUUID(), ConnectionType.DISCORD), + emptyBody, + VerificationCodeSchema.class + ).sendRequestAsync((response) -> { + if(!response.successful()) { + consumer.accept(new ApiResponse<>(false, null, response.error())); + return; + } + consumer.accept(new ApiResponse<>(true, response.data().code, null)); + }); + } + + /** + * A request to unlink the discord account of {@link GlobalTagsAPI#getClientUUID()} + * + * @param consumer The action to be executed on response. + */ + public void unlinkDiscord(Consumer> consumer) { + new ApiRequest<>( + api, + "DELETE", + Routes.connection(api.getClientUUID(), ConnectionType.DISCORD), + emptyBody, + MessageSchema.class + ).sendRequestAsync((response) -> { + if(!response.successful()) { + consumer.accept(new ApiResponse<>(false, null, response.error())); + return; + } + api.getCache().renewSelf((info) -> + consumer.accept(new ApiResponse<>(true, response.data().message, null)) + ); + }); + } + + /** + * A request to send an email verification to of {@link GlobalTagsAPI#getClientUUID()}. + * + * @param email The email which should be linked + * @param consumer The action to be executed on response. + */ + public void linkEmail(String email, Consumer> consumer) { + new ApiRequest<>( + api, + "POST", + Routes.connection(api.getClientUUID(), ConnectionType.EMAIL), + Map.of("email", email), + MessageSchema.class + ).sendRequestAsync((response) -> { + if(!response.successful()) { + consumer.accept(new ApiResponse<>(false, null, response.error())); + return; + } + consumer.accept(new ApiResponse<>(true, response.data().message, null)); + }); + } + + /** + * A request to unlink the email address of {@link GlobalTagsAPI#getClientUUID()} + * + * @param consumer The action to be executed on response. + */ + public void unlinkEmail(Consumer> consumer) { + new ApiRequest<>( + api, + "DELETE", + Routes.connection(api.getClientUUID(), ConnectionType.EMAIL), + emptyBody, + MessageSchema.class + ).sendRequestAsync((response) -> { + if(!response.successful()) { + consumer.accept(new ApiResponse<>(false, null, response.error())); + return; + } + consumer.accept(new ApiResponse<>(true, response.data().message, null)); + }); + } + + /** + * A request to verify the email with the received verification code. + * + * @param code The verification code which was received via email + * @param consumer The action to be executed on response. + */ + public void verifyEmail(String code, Consumer> consumer) { + new ApiRequest<>( + api, + "POST", + Routes.verifyEmail(api.getClientUUID(), code), + emptyBody, + MessageSchema.class + ).sendRequestAsync((response) -> { + if(!response.successful()) { + consumer.accept(new ApiResponse<>(false, null, response.error())); + return; + } + consumer.accept(new ApiResponse<>(true, response.data().message, null)); + }); + } + + /** + * A request to get all notes of {@link GlobalTagsAPI#getClientUUID()} + * + * @param consumer The action to be executed on response. + */ + public void getNotes(Consumer>> consumer) { + getNotes(api.getClientUUID(), consumer); + } + + /** + * A request to get all notes of a specific uuid + * + * @param uuid The uuid of the player + * @param consumer The action to be executed on response. + */ + public void getNotes(UUID uuid, Consumer>> consumer) { + new ApiRequest<>( + api, + "GET", + Routes.notes(uuid), + emptyBody, + NoteSchema[].class + ).sendRequestAsync((response) -> { + if(!response.successful()) { + consumer.accept(new ApiResponse<>(false, null, response.error())); + return; + } + List notes = new ArrayList<>(); + for(NoteSchema note : response.data()) { + notes.add(new PlayerNote( + note.id, + note.text, + note.author, + note.createdAt + )); + } + consumer.accept(new ApiResponse<>(true, notes, null)); + }); + } + + /** + * A request to create a note for {@link GlobalTagsAPI#getClientUUID()} + * + * @param note The note which should be created + * @param consumer The action to be executed on response. + */ + public void createNote(String note, Consumer> consumer) { + createNote(api.getClientUUID(), note, consumer); + } + + /** + * A request to create a note for a specific uuid + * + * @param uuid The uuid of the player + * @param note The note which should be created + * @param consumer The action to be executed on response. + */ + public void createNote(UUID uuid, String note, Consumer> consumer) { + new ApiRequest<>( + api, + "POST", + Routes.notes(uuid), + Map.of("note", note), + MessageSchema.class + ).sendRequestAsync((response) -> { + if(!response.successful()) { + consumer.accept(new ApiResponse<>(false, null, response.error())); + return; + } + consumer.accept(new ApiResponse<>(true, response.data().message, null)); + }); + } + + /** + * A request to get a specific note of {@link GlobalTagsAPI#getClientUUID()} + * + * @param noteId The ID of the note to get + * @param consumer The action to be executed on response. + */ + public void getNote(String noteId, Consumer> consumer) { + getNote(api.getClientUUID(), noteId, consumer); + } + + /** + * A request to get a specific note of {@link GlobalTagsAPI#getClientUUID()} + * + * @param uuid The uuid of the player + * @param noteId The ID of the note to get + * @param consumer The action to be executed on response. + */ + public void getNote(UUID uuid, String noteId, Consumer> consumer) { + new ApiRequest<>( + api, + "GET", + Routes.note(uuid, noteId), + emptyBody, + NoteSchema.class + ).sendRequestAsync((response) -> { + if(!response.successful()) { + consumer.accept(new ApiResponse<>(false, null, response.error())); + return; + } + NoteSchema body = response.data(); + consumer.accept(new ApiResponse<>( + false, + new PlayerNote( + body.id, + body.text, + body.author, + body.createdAt + ), + null + )); + }); + } + + /** + * Deletes a note of {@link GlobalTagsAPI#getClientUUID()}. + * + * @param noteId The ID of the note to delete. + * @param consumer The action to be executed on response. + */ + public void deleteNote(String noteId, Consumer> consumer) { + deleteNote(api.getClientUUID(), noteId, consumer); + } + + /** + * Deletes a note of a specific uuid. + * + * @param uuid The UUID of the player whose note you want to delete. + * @param noteId The ID of the note to delete. + * @param consumer The action to be executed on response. + */ + public void deleteNote(UUID uuid, String noteId, Consumer> consumer) { + new ApiRequest<>( + api, + "DELETE", + Routes.note(uuid, noteId), + emptyBody, + MessageSchema.class + ).sendRequestAsync((response) -> { + if(!response.successful()) { + consumer.accept(new ApiResponse<>(false, null, response.error())); + return; + } + consumer.accept(new ApiResponse<>(true, response.data().message, null)); + }); + } + + /** + * An inline class containing response data for these requests + * @param The type of the data + */ + public static class ApiResponse { + + private final boolean successful; + private final T data; + private final String error; + + /** + * Constructs a new ApiResponse instance + * + * @param successful If the request was successful + * @param data The data returned if available + * @param error The error returned if available + */ + public ApiResponse(boolean successful, T data, String error) { + this.successful = successful; + this.data = data; + this.error = error; + } + + public boolean successful() { + return successful; + } + + public T data() { + return data; + } + + public String error() { + return error; + } + } +} diff --git a/src/main/java/com/rappytv/globaltags/wrapper/http/ApiRequest.java b/src/main/java/com/rappytv/globaltags/wrapper/http/ApiRequest.java index a86409e..acba4e6 100644 --- a/src/main/java/com/rappytv/globaltags/wrapper/http/ApiRequest.java +++ b/src/main/java/com/rappytv/globaltags/wrapper/http/ApiRequest.java @@ -64,9 +64,9 @@ public ApiRequest(GlobalTagsAPI api, String method, String path, Map> consumer) { try { - HttpRequest request = getBuilder() - .uri(new URI(api.getUrls().getApiBase() + path)) - .method(method, getBodyPublisher()) + HttpRequest request = this.getBuilder() + .uri(new URI(this.api.getUrls().getApiBase() + this.path)) + .method(this.method, this.getBodyPublisher()) .build(); client.sendAsync(request, HttpResponse.BodyHandlers.ofString()).thenAccept(response -> { @@ -76,19 +76,17 @@ public void sendRequestAsync(Consumer<@NotNull ResponseBody> consumer) { consumer.accept(new ResponseBody<>(false, null, body.error)); return; } - T parsedBody = gson.fromJson(response.body(), responseType); + T parsedBody = gson.fromJson(response.body(), this.responseType); consumer.accept(new ResponseBody<>( - response.statusCode() >= 200 && response.statusCode() < 300, + true, parsedBody, null )); }).exceptionally(throwable -> { - throwable.printStackTrace(); consumer.accept(new ResponseBody<>(false, null, throwable.getLocalizedMessage())); return null; }); } catch (Exception e) { - e.printStackTrace(); consumer.accept(new ResponseBody<>(false, null, e.getLocalizedMessage())); } } @@ -101,9 +99,9 @@ public void sendRequestAsync(Consumer<@NotNull ResponseBody> consumer) { private HttpRequest.Builder getBuilder() { return HttpRequest.newBuilder() .header("Content-Type", "application/json") - .header("Authorization", api.getAuthorizationHeader()) - .header("X-Language", api.getLanguageCode()) - .header("X-Agent", api.getAgent().toString()); + .header("Authorization", this.api.getAuthorizationHeader()) + .header("X-Language", this.api.getLanguageCode()) + .header("X-Agent", this.api.getAgent().toString()); } /** @@ -112,17 +110,58 @@ private HttpRequest.Builder getBuilder() { * @return The {@link HttpRequest.BodyPublisher} from the data parameter */ private HttpRequest.BodyPublisher getBodyPublisher() { - if (body == null || body.isEmpty()) return HttpRequest.BodyPublishers.noBody(); - return HttpRequest.BodyPublishers.ofString(gson.toJson(body)); + if (this.body == null || this.body.isEmpty()) return HttpRequest.BodyPublishers.noBody(); + return HttpRequest.BodyPublishers.ofString(gson.toJson(this.body)); } /** - * A record which passes a lightweight API response to consumers. + * A class which passes a lightweight API response to consumers. * - * @param successful If the request was successful - * @param data The response data - * @param error An error message - * @param The type of the response data + * @param The return type */ - public record ResponseBody(boolean successful, T data, String error) {} + public static class ResponseBody { + + private final boolean successful; + private final T data; + private final String error; + + /** + * Constructs a new response body. + * + * @param successful If the request was successful + * @param data The response data + * @param error An error message + */ + public ResponseBody(boolean successful, T data, String error) { + this.successful = successful; + this.data = data; + this.error = error; + } + + /** + * Checks if the request was successful + * + * @return If the request was successful + */ + public boolean isSuccessful() { + return this.successful; + } + + /** + * Gets the data returned if available + * + * @return the data if available + */ + public T getData() { + return this.data; + } + + /** + * Get the error returned if available + * @return an error if available + */ + public String getError() { + return this.error; + } + } } diff --git a/src/main/java/com/rappytv/globaltags/wrapper/http/Routes.java b/src/main/java/com/rappytv/globaltags/wrapper/http/Routes.java index 5102779..7cf0953 100644 --- a/src/main/java/com/rappytv/globaltags/wrapper/http/Routes.java +++ b/src/main/java/com/rappytv/globaltags/wrapper/http/Routes.java @@ -52,6 +52,18 @@ public static String getMetrics() { return "/metrics"; } + /** + *
+     * Route for
+     * - GET /referrals
+     * 
+ * + * @return The HTTP route + */ + public static String getReferralLeaderboards() { + return "/referrals"; + } + /** *
      * Route for
diff --git a/src/main/java/com/rappytv/globaltags/wrapper/http/schemas/PlayerInfoSchema.java b/src/main/java/com/rappytv/globaltags/wrapper/http/schemas/PlayerInfoSchema.java
index 59dc8ee..c48e833 100644
--- a/src/main/java/com/rappytv/globaltags/wrapper/http/schemas/PlayerInfoSchema.java
+++ b/src/main/java/com/rappytv/globaltags/wrapper/http/schemas/PlayerInfoSchema.java
@@ -7,8 +7,7 @@ public class PlayerInfoSchema {
     public String tag;
     public String position;
     public PlayerInfo.Icon icon;
-    public boolean referred;
-    public int referrals;
+    public PlayerInfo.ReferralInfo referrals;
     public String[] roles;
     public String[] permissions;
     public PlayerInfo.Suspension ban;
diff --git a/src/main/java/com/rappytv/globaltags/wrapper/http/schemas/ReferralLeaderboardsSchema.java b/src/main/java/com/rappytv/globaltags/wrapper/http/schemas/ReferralLeaderboardsSchema.java
new file mode 100644
index 0000000..7784b44
--- /dev/null
+++ b/src/main/java/com/rappytv/globaltags/wrapper/http/schemas/ReferralLeaderboardsSchema.java
@@ -0,0 +1,23 @@
+package com.rappytv.globaltags.wrapper.http.schemas;
+
+import com.google.gson.annotations.SerializedName;
+
+public class ReferralLeaderboardsSchema {
+
+    @SerializedName("total")
+    public ReferralLeaderboardEntrySchema[] totalLeaderboard;
+
+    @SerializedName("current_month")
+    public ReferralLeaderboardEntrySchema[] currentMonthLeaderboard;
+
+    public static class ReferralLeaderboardEntrySchema {
+
+        public String uuid;
+
+        @SerializedName("total_referrals")
+        public int totalReferrals;
+
+        @SerializedName("current_month_referrals")
+        public int currentMonthReferrals;
+    }
+}
diff --git a/src/main/java/com/rappytv/globaltags/wrapper/model/ApiInfo.java b/src/main/java/com/rappytv/globaltags/wrapper/model/ApiInfo.java
index 5180792..729d921 100644
--- a/src/main/java/com/rappytv/globaltags/wrapper/model/ApiInfo.java
+++ b/src/main/java/com/rappytv/globaltags/wrapper/model/ApiInfo.java
@@ -4,22 +4,36 @@
 
 /**
  * Represents information about the API, including the version, number of requests, and commit details.
- *
- * @param version the version of the API, must not be null
- * @param requests the number of requests made to the API
- * @param commit the commit data related to the API, must not be null
  */
-public record ApiInfo(@NotNull String version, int requests, @NotNull CommitData commit) {
+public class ApiInfo {
+
+    private final String version;
+    private final int requests;
+    private final CommitData commit;
+
+    /**
+     * Creates a new instance of ApiInfo.
+     *
+     * @param version the version of the API, must not be null
+     * @param requests the number of requests made to the API
+     * @param branch the branch associated with the commit, must not be null
+     * @param sha the commit SHA hash, must not be null
+     * @param tree the tree SHA hash, must not be null
+     */
+    public ApiInfo(@NotNull String version, int requests, @NotNull String branch, @NotNull String sha, @NotNull String tree) {
+        this.version = version;
+        this.requests = requests;
+        this.commit = new CommitData(branch, sha, tree);
+    }
 
     /**
      * Retrieves the version of the API.
      *
      * @return the API version, never null
      */
-    @Override
     @NotNull
-    public String version() {
-        return version;
+    public String getVersion() {
+        return this.version;
     }
 
     /**
@@ -27,9 +41,8 @@ public String version() {
      *
      * @return the number of requests
      */
-    @Override
-    public int requests() {
-        return requests;
+    public int getRequests() {
+        return this.requests;
     }
 
     /**
@@ -37,30 +50,41 @@ public int requests() {
      *
      * @return the commit data, never null
      */
-    @Override
     @NotNull
-    public CommitData commit() {
-        return commit;
+    public CommitData getCommit() {
+        return this.commit;
     }
 
     /**
      * Represents data related to a Git commit, including the branch, SHA, and tree information.
-     *
-     * @param branch the branch associated with the commit, must not be null
-     * @param sha    the commit SHA hash, must not be null
-     * @param tree   the tree SHA hash, must not be null
      */
-    public record CommitData(@NotNull String branch, @NotNull String sha, @NotNull String tree) {
+    public static class CommitData {
+
+        private final String branch;
+        private final String sha;
+        private final String tree;
+
+        /**
+         * Creates a new instance of CommitData.
+         *
+         * @param branch the branch associated with the commit, must not be null
+         * @param sha    the commit SHA hash, must not be null
+         * @param tree   the tree SHA hash, must not be null
+         */
+        public CommitData(@NotNull String branch, @NotNull String sha, @NotNull String tree) {
+            this.branch = branch;
+            this.sha = sha;
+            this.tree = tree;
+        }
 
         /**
          * Retrieves the branch associated with this commit.
          *
          * @return the branch name, never null
          */
-        @Override
         @NotNull
-        public String branch() {
-            return branch;
+        public String getBranch() {
+            return this.branch;
         }
 
         /**
@@ -68,10 +92,9 @@ public String branch() {
          *
          * @return the commit SHA hash, never null
          */
-        @Override
         @NotNull
-        public String sha() {
-            return sha;
+        public String getSha() {
+            return this.sha;
         }
 
         /**
@@ -79,10 +102,9 @@ public String sha() {
          *
          * @return the tree SHA hash, never null
          */
-        @Override
         @NotNull
-        public String tree() {
-            return tree;
+        public String getTree() {
+            return this.tree;
         }
     }
 }
diff --git a/src/main/java/com/rappytv/globaltags/wrapper/model/PlayerInfo.java b/src/main/java/com/rappytv/globaltags/wrapper/model/PlayerInfo.java
index 8e47c38..0c7fc20 100644
--- a/src/main/java/com/rappytv/globaltags/wrapper/model/PlayerInfo.java
+++ b/src/main/java/com/rappytv/globaltags/wrapper/model/PlayerInfo.java
@@ -1,15 +1,15 @@
 package com.rappytv.globaltags.wrapper.model;
 
+import com.google.gson.annotations.SerializedName;
+import com.rappytv.globaltags.wrapper.GlobalTagsAPI;
 import com.rappytv.globaltags.wrapper.enums.GlobalIcon;
 import com.rappytv.globaltags.wrapper.enums.GlobalPermission;
 import com.rappytv.globaltags.wrapper.enums.GlobalPosition;
 import com.rappytv.globaltags.wrapper.enums.GlobalRole;
-import com.rappytv.globaltags.wrapper.GlobalTagsAPI;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
 import java.util.*;
-import java.util.Timer;
 import java.util.function.Consumer;
 
 /**
@@ -26,24 +26,23 @@ public class PlayerInfo {
     private final String plainTag;
     private final String position;
     private final Icon icon;
-    private final boolean referred;
-    private final int referrals;
+    private final ReferralInfo referralInfo;
     private final List roles;
     private final Map permissions;
     private final Suspension suspension;
 
     /**
      * Build a new PlayerInfo instance
-     * @param api The {@link GlobalTagsAPI} for the {@link GlobalTagsAPI#translateColorCodes(String)} method
-     * @param uuid The player's {@link UUID}
-     * @param tag The player's plain tag including color codes
-     * @param position The player's global position as a string
-     * @param icon The player's global icon as a string
-     * @param referred If the player has already marked someone as their inviter
-     * @param referrals How many players the player has invited
-     * @param roles The player's roles
-     * @param permissions The player's permissions
-     * @param suspension The player's {@link Suspension}
+     *
+     * @param api          The {@link GlobalTagsAPI} for the {@link GlobalTagsAPI#translateColorCodes(String)} method
+     * @param uuid         The player's {@link UUID}
+     * @param tag          The player's plain tag including color codes
+     * @param position     The player's global position as a string
+     * @param icon         The player's global icon as a string
+     * @param referralInfo The player's referral info
+     * @param roles        The player's roles
+     * @param permissions  The player's permissions
+     * @param suspension   The player's {@link Suspension}
      */
     public PlayerInfo(
             @NotNull GlobalTagsAPI api,
@@ -51,8 +50,7 @@ public PlayerInfo(
             @Nullable String tag,
             @NotNull String position,
             @NotNull Icon icon,
-            boolean referred,
-            int referrals,
+            ReferralInfo referralInfo,
             @NotNull String[] roles,
             @NotNull String[] permissions,
             @Nullable Suspension suspension
@@ -63,23 +61,24 @@ public PlayerInfo(
         this.plainTag = tag != null ? tag : "";
         this.position = position;
         this.icon = icon;
-        this.referred = referred;
-        this.referrals = referrals;
+        this.referralInfo = referralInfo;
         this.roles = new ArrayList<>();
-        for(String role : roles) {
+        for (String role : roles) {
             try {
                 this.roles.add(GlobalRole.valueOf(role.toUpperCase()));
-            } catch (Exception ignored) {}
+            } catch (Exception ignored) {
+            }
         }
         this.permissions = new HashMap<>();
         List playerPermissions = new ArrayList<>();
-        for(String permission : permissions) {
+        for (String permission : permissions) {
             GlobalPermission globalPermission;
             try {
                 playerPermissions.add(GlobalPermission.valueOf(permission.toUpperCase()));
-            } catch (Exception ignored) {}
+            } catch (Exception ignored) {
+            }
         }
-        for(GlobalPermission permission : GlobalPermission.values()) {
+        for (GlobalPermission permission : GlobalPermission.values()) {
             this.permissions.put(permission, playerPermissions.contains(permission));
         }
         this.suspension = suspension != null ? suspension : new Suspension();
@@ -92,7 +91,7 @@ public PlayerInfo(
      */
     @NotNull
     public UUID getUUID() {
-        return uuid;
+        return this.uuid;
     }
 
     /**
@@ -102,7 +101,7 @@ public UUID getUUID() {
      */
     @Nullable
     public T getTag() {
-        return !plainTag.isBlank() ? tag : null;
+        return !this.plainTag.isBlank() ? this.tag : null;
     }
 
     /**
@@ -112,7 +111,7 @@ public T getTag() {
      */
     @NotNull
     public String getPlainTag() {
-        return plainTag;
+        return this.plainTag;
     }
 
     /**
@@ -123,7 +122,7 @@ public String getPlainTag() {
     @NotNull
     public GlobalPosition getPosition() {
         try {
-            return GlobalPosition.valueOf(position);
+            return GlobalPosition.valueOf(this.position);
         } catch (Exception ignored) {
             return GlobalPosition.ABOVE;
         }
@@ -137,7 +136,7 @@ public GlobalPosition getPosition() {
     @NotNull
     public GlobalIcon getGlobalIcon() {
         try {
-            return GlobalIcon.valueOf(icon.type);
+            return GlobalIcon.valueOf(this.icon.type);
         } catch (Exception ignored) {
             return GlobalIcon.NONE;
         }
@@ -150,7 +149,7 @@ public GlobalIcon getGlobalIcon() {
      */
     @Nullable
     public String getGlobalIconHash() {
-        return icon.hash;
+        return this.icon.hash;
     }
 
     /**
@@ -159,7 +158,7 @@ public String getGlobalIconHash() {
      * @return {@code true} if the player has a custom global icon; otherwise {@code false}.
      */
     public boolean hasCustomGlobalIcon() {
-        return getGlobalIcon() == GlobalIcon.CUSTOM && icon.hash != null;
+        return this.getGlobalIcon() == GlobalIcon.CUSTOM && this.icon.hash != null;
     }
 
     /**
@@ -169,8 +168,8 @@ public boolean hasCustomGlobalIcon() {
      */
     @NotNull
     public String getIconUrl() {
-        if(hasCustomGlobalIcon()) return urls.getCustomIcon(uuid, icon.hash);
-        return urls.getDefaultIcon(getGlobalIcon());
+        if (this.hasCustomGlobalIcon()) return this.urls.getCustomIcon(this.uuid, this.icon.hash);
+        return this.urls.getDefaultIcon(this.getGlobalIcon());
     }
 
     /**
@@ -180,7 +179,16 @@ public String getIconUrl() {
      * @return {@code true} if the player has the specified permission; otherwise {@code false}.
      */
     public boolean hasPermission(GlobalPermission permission) {
-        return permissions.containsKey(permission) && permissions.get(permission);
+        return this.permissions.containsKey(permission) && this.permissions.get(permission);
+    }
+
+    /**
+     * Gets the number of players this player has invited.
+     *
+     * @return The number of players invited by this player.
+     */
+    public ReferralInfo getReferralInfo() {
+        return this.referralInfo;
     }
 
     /**
@@ -189,16 +197,25 @@ public boolean hasPermission(GlobalPermission permission) {
      * @return {@code true} if the player has referred another player; otherwise {@code false}.
      */
     public boolean hasReferred() {
-        return referred;
+        return this.getReferralInfo().hasReferred();
     }
 
     /**
-     * Gets the number of players this player has invited.
+     * Gets the total number of referrals the player has made.
      *
-     * @return The number of players invited by this player.
+     * @return The total number of referrals.
+     */
+    public int getTotalReferrals() {
+        return this.getReferralInfo().getTotalReferrals();
+    }
+
+    /**
+     * Gets the number of referrals the player has made in the current month.
+     *
+     * @return The number of referrals in the current month.
      */
-    public int getReferrals() {
-        return referrals;
+    public int getCurrentMonthReferrals() {
+        return this.getReferralInfo().getCurrentMonthReferrals();
     }
 
     /**
@@ -208,7 +225,7 @@ public int getReferrals() {
      */
     @NotNull
     public List getRoles() {
-        return roles;
+        return this.roles;
     }
 
     /**
@@ -218,8 +235,8 @@ public List getRoles() {
      */
     @Nullable
     public GlobalRole getHighestRole() {
-        for(GlobalRole role : GlobalRole.values()) {
-            if(roles.contains(role)) return role;
+        for (GlobalRole role : GlobalRole.values()) {
+            if (this.roles.contains(role)) return role;
         }
         return null;
     }
@@ -231,9 +248,9 @@ public GlobalRole getHighestRole() {
      */
     @Nullable
     public String getHighestRoleIcon() {
-        GlobalRole role = getHighestRole();
-        if(role == null) return null;
-        return urls.getRoleIcon(role);
+        GlobalRole role = this.getHighestRole();
+        if (role == null) return null;
+        return this.urls.getRoleIcon(role);
     }
 
     /**
@@ -242,7 +259,7 @@ public String getHighestRoleIcon() {
      * @return {@code true} if the player is suspended; otherwise {@code false}.
      */
     public boolean isSuspended() {
-        return suspension.active;
+        return this.suspension.active;
     }
 
     /**
@@ -252,32 +269,116 @@ public boolean isSuspended() {
      */
     @NotNull
     public Suspension getSuspension() {
-        return suspension;
+        return this.suspension;
     }
 
     @Override
     public String toString() {
-        return String.format(
-                "Playerinfo{uuid=%s, tag='%s', position='%s', icon='%s', referred=%s, referrals=%s, roles=%s, permissions=%s, suspension=%s}",
-                uuid,
-                plainTag,
-                getPosition().name().toLowerCase(),
-                icon,
-                referred,
-                referrals,
-                roles,
-                permissions,
-                suspension
-        );
+        return "PlayerInfo{" +
+                "uuid=" + this.uuid +
+                ", tag=" + this.tag +
+                ", plainTag='" + this.plainTag + '\'' +
+                ", position=" + this.getPosition() +
+                ", icon=PlayerIcon{type=" + this.getGlobalIcon() +
+                ", hash=" + this.getGlobalIconHash() + '}' +
+                ", referralInfo=" + this.referralInfo +
+                ", roles=" + this.roles +
+                ", permissions=" + this.permissions +
+                ", suspension=" + this.suspension +
+                '}';
     }
 
     /**
      * Represents an icon for a player in the response body.
-     *
-     * @param type The {@link GlobalIcon} type.
-     * @param hash The custom icon hash.
      */
-    public record Icon(String type, String hash) {}
+    public static class Icon {
+
+        private final String type;
+        private final String hash;
+
+        /**
+         * Creates a new icon.
+         *
+         * @param type The {@link GlobalIcon} type.
+         * @param hash The custom icon hash.
+         */
+        public Icon(String type, String hash) {
+            this.type = type;
+            this.hash = hash;
+        }
+
+        @Override
+        public String toString() {
+            return "Icon{" +
+                    "type='" + this.type + '\'' +
+                    ", hash='" + this.hash + '\'' +
+                    '}';
+        }
+    }
+
+    /**
+     * Holds information about a player's referrals.
+     */
+    public static class ReferralInfo {
+
+        @SerializedName("has_referred")
+        private final boolean hasReferred;
+
+        @SerializedName("total_referrals")
+        private final int totalReferrals;
+
+        @SerializedName("current_month_referrals")
+        private final int currentMonthReferrals;
+
+        /**
+         * Builds a new {@link ReferralInfo}
+         *
+         * @param hasReferred           If the player has already marked someone as their inviter
+         * @param totalReferrals        The total number of players the player has invited
+         * @param currentMonthReferrals The number of players the player has invited in the current month
+         */
+        public ReferralInfo(boolean hasReferred, int totalReferrals, int currentMonthReferrals) {
+            this.hasReferred = hasReferred;
+            this.totalReferrals = totalReferrals;
+            this.currentMonthReferrals = currentMonthReferrals;
+        }
+
+        /**
+         * Checks if the player has already marked someone as their inviter.
+         *
+         * @return {@code true} if the player has already marked someone as their inviter; otherwise {@code false}.
+         */
+        public boolean hasReferred() {
+            return this.hasReferred;
+        }
+
+        /**
+         * Gets the total number of players the player has invited.
+         *
+         * @return The total number of players the player has invited.
+         */
+        public int getTotalReferrals() {
+            return this.totalReferrals;
+        }
+
+        /**
+         * Gets the number of players the player has invited in the current month.
+         *
+         * @return The number of players the player has invited in the current month.
+         */
+        public int getCurrentMonthReferrals() {
+            return this.currentMonthReferrals;
+        }
+
+        @Override
+        public String toString() {
+            return "ReferralInfo{" +
+                    "hasReferred=" + this.hasReferred +
+                    ", totalReferrals=" + this.totalReferrals +
+                    ", currentMonthReferrals=" + this.currentMonthReferrals +
+                    '}';
+        }
+    }
 
     /**
      * Represents a player's ban or suspension status.
@@ -300,7 +401,7 @@ public Suspension() {
         /**
          * Creates an active suspension.
          *
-         * @param reason The reason for the suspension.
+         * @param reason     The reason for the suspension.
          * @param appealable Whether the suspension is appealable.
          */
         public Suspension(String reason, boolean appealable) {
@@ -311,35 +412,38 @@ public Suspension(String reason, boolean appealable) {
 
         /**
          * Returns if the suspension is active or not
+         *
          * @return If the suspension is active or not
          */
         public boolean isActive() {
-            return active;
+            return this.active;
         }
 
         /**
          * Returns the suspension reason
+         *
          * @return Returns the suspension reason
          */
         @Nullable
         public String getReason() {
-            return reason;
+            return this.reason;
         }
 
         /**
          * Returns if the suspension can be appealed
+         *
          * @return If the suspension can be appealed
          */
         public boolean isAppealable() {
-            return appealable;
+            return this.appealable;
         }
 
         @Override
         public String toString() {
             return "Suspension{" +
-                    "active=" + active +
-                    ", reason='" + reason + '\'' +
-                    ", appealable=" + appealable +
+                    "active=" + this.active +
+                    ", reason='" + this.reason + '\'' +
+                    ", appealable=" + this.appealable +
                     '}';
         }
     }
@@ -353,6 +457,8 @@ public static class Cache {
 
         private final static Timer timer = new Timer();
         private final GlobalTagsAPI api;
+        private final Map> cache = new HashMap<>();
+        private final Set resolving = new HashSet<>();
 
         /**
          * Initializes a cache with default cleanup intervals.
@@ -385,17 +491,17 @@ public Cache(@NotNull GlobalTagsAPI api, @NotNull Options options) {
             Objects.requireNonNull(api, "api must not be null");
             Objects.requireNonNull(options, "options may not be null");
             this.api = api;
-            if(options.getCacheClearInterval() > -1) {
+            if (options.getCacheClearInterval() > -1) {
                 timer.scheduleAtFixedRate(new TimerTask() {
                     @Override
                     public void run() {
                         api.getCache().clear();
-                        if(api.getClientUUID() != null) api.getCache().resolveSelf();
+                        if (api.getClientUUID() != null) api.getCache().resolveSelf();
                     }
                 }, options.getCacheClearInterval(), options.getCacheClearInterval());
             }
 
-            if(options.getCacheRenewInterval() > -1) {
+            if (options.getCacheRenewInterval() > -1) {
                 timer.scheduleAtFixedRate(new TimerTask() {
                     @Override
                     public void run() {
@@ -405,9 +511,6 @@ public void run() {
             }
         }
 
-        private final Map> cache = new HashMap<>();
-        private final Set resolving = new HashSet<>();
-
         /**
          * Adds a {@link PlayerInfo} to the cache
          *
@@ -415,14 +518,14 @@ public void run() {
          * @param info The {@link PlayerInfo}
          */
         public void add(UUID uuid, PlayerInfo info) {
-            cache.put(uuid, info);
+            this.cache.put(uuid, info);
         }
 
         /**
          * Removes the {@link GlobalTagsAPI#getClientUUID()} from the cache
          */
         public void removeSelf() {
-            remove(api.getClientUUID());
+            this.remove(this.api.getClientUUID());
         }
 
         /**
@@ -431,7 +534,7 @@ public void removeSelf() {
          * @param uuid The corresponding {@link UUID}
          */
         public void remove(UUID uuid) {
-            cache.remove(uuid);
+            this.cache.remove(uuid);
         }
 
         /**
@@ -441,7 +544,7 @@ public void remove(UUID uuid) {
          * @return If the player is in the cache
          */
         public boolean has(UUID uuid) {
-            return cache.containsKey(uuid);
+            return this.cache.containsKey(uuid);
         }
 
         /**
@@ -452,14 +555,15 @@ public boolean has(UUID uuid) {
          */
         @Nullable
         public PlayerInfo get(UUID uuid) {
-            return cache.get(uuid);
+            return this.cache.get(uuid);
         }
 
         /**
          * Resolve the UUID {@link GlobalTagsAPI#getClientUUID()} into the cache
          */
         public void resolveSelf() {
-            resolveSelf((info) -> {});
+            this.resolveSelf((info) -> {
+            });
         }
 
         /**
@@ -468,7 +572,7 @@ public void resolveSelf() {
          * @param consumer A consumer returning the resolved {@link PlayerInfo}
          */
         public void resolveSelf(Consumer<@Nullable PlayerInfo> consumer) {
-            resolve(api.getClientUUID(), consumer);
+            this.resolve(this.api.getClientUUID(), consumer);
         }
 
         /**
@@ -477,37 +581,38 @@ public void resolveSelf(Consumer<@Nullable PlayerInfo> consumer) {
          * @param uuid The uuid which should be resolved
          */
         public void resolve(UUID uuid) {
-            resolve(uuid, (info) -> {});
+            this.resolve(uuid, (info) -> {
+            });
         }
 
         /**
          * Resolve a specific {@link UUID} into the cache
          *
-         * @param uuid The uuid which should be resolved
+         * @param uuid     The uuid which should be resolved
          * @param consumer A consumer returning the resolved {@link PlayerInfo}
          */
         public void resolve(UUID uuid, Consumer<@Nullable PlayerInfo> consumer) {
-            if(has(uuid)) {
-                consumer.accept(get(uuid));
+            if (this.has(uuid)) {
+                consumer.accept(this.get(uuid));
                 return;
             }
-            fetch(uuid, consumer);
+            this.fetch(uuid, consumer);
         }
 
         /**
          * Fetches a specific {@link UUID}
          *
-         * @param uuid The uuid which should be fetched
+         * @param uuid     The uuid which should be fetched
          * @param consumer A consumer returning the resolved {@link PlayerInfo}
          */
         private void fetch(UUID uuid, Consumer<@Nullable PlayerInfo> consumer) {
-            if(resolving.contains(uuid)) return;
-            resolving.add(uuid);
+            if (this.resolving.contains(uuid)) return;
+            this.resolving.add(uuid);
 
-            api.getApiHandler().getInfo(uuid, (info) -> {
-                add(uuid, info.data());
-                resolving.remove(uuid);
-                resolve(uuid, consumer);
+            this.api.getApiHandler().getInfo(uuid, (info) -> {
+                this.add(uuid, info.getData());
+                this.resolving.remove(uuid);
+                this.resolve(uuid, consumer);
             });
         }
 
@@ -515,7 +620,8 @@ private void fetch(UUID uuid, Consumer<@Nullable PlayerInfo> consumer) {
          * Renews tag data of {@link GlobalTagsAPI#getClientUUID()}
          */
         public void renewSelf() {
-            renewSelf((info) -> {});
+            this.renewSelf((info) -> {
+            });
         }
 
         /**
@@ -524,7 +630,7 @@ public void renewSelf() {
          * @param consumer A consumer returning the renewed {@link PlayerInfo}
          */
         public void renewSelf(Consumer<@Nullable PlayerInfo> consumer) {
-            renew(api.getClientUUID(), consumer);
+            this.renew(this.api.getClientUUID(), consumer);
         }
 
         /**
@@ -533,18 +639,19 @@ public void renewSelf(Consumer<@Nullable PlayerInfo> consumer) {
          * @param uuid The uuid which should be renewed
          */
         public void renew(UUID uuid) {
-            renew(uuid, (info) -> {});
+            this.renew(uuid, (info) -> {
+            });
         }
 
         /**
          * Renews tag data of a specific uuid
          *
-         * @param uuid The uuid which should be renewed
+         * @param uuid     The uuid which should be renewed
          * @param consumer A consumer returning the renewed {@link PlayerInfo}
          */
         public void renew(UUID uuid, Consumer<@Nullable PlayerInfo> consumer) {
-            fetch(uuid, (info) -> {
-                cache.put(uuid, info);
+            this.fetch(uuid, (info) -> {
+                this.cache.put(uuid, info);
                 consumer.accept(info);
             });
         }
@@ -553,8 +660,8 @@ public void renew(UUID uuid, Consumer<@Nullable PlayerInfo> consumer) {
          * Renews tag data of all cached uuids
          */
         public void renewAll() {
-            for(UUID uuid : cache.keySet()) {
-                renew(uuid);
+            for (UUID uuid : this.cache.keySet()) {
+                this.renew(uuid);
             }
         }
 
@@ -562,8 +669,8 @@ public void renewAll() {
          * Clears the cache
          */
         public void clear() {
-            cache.clear();
-            resolving.clear();
+            this.cache.clear();
+            this.resolving.clear();
         }
 
         /**
diff --git a/src/main/java/com/rappytv/globaltags/wrapper/model/PlayerNote.java b/src/main/java/com/rappytv/globaltags/wrapper/model/PlayerNote.java
index 1df0463..db0e527 100644
--- a/src/main/java/com/rappytv/globaltags/wrapper/model/PlayerNote.java
+++ b/src/main/java/com/rappytv/globaltags/wrapper/model/PlayerNote.java
@@ -42,7 +42,7 @@ public PlayerNote(
      */
     @NotNull
     public String getId() {
-        return id;
+        return this.id;
     }
 
     /**
@@ -52,7 +52,7 @@ public String getId() {
      */
     @NotNull
     public String getText() {
-        return text;
+        return this.text;
     }
 
     /**
@@ -62,7 +62,7 @@ public String getText() {
      */
     @NotNull
     public UUID getAuthor() {
-        return author;
+        return this.author;
     }
 
     /**
@@ -71,16 +71,16 @@ public UUID getAuthor() {
      * @return The date and time when the note was created.
      */
     public Date getCreatedAt() {
-        return createdAt;
+        return this.createdAt;
     }
 
     @Override
     public String toString() {
         return "PlayerNote{" +
-                "id='" + id + '\'' +
-                ", text='" + text + '\'' +
-                ", author=" + author +
-                ", createdAt=" + createdAt +
+                "id='" + this.id + '\'' +
+                ", text='" + this.text + '\'' +
+                ", author=" + this.author +
+                ", createdAt=" + this.createdAt +
                 '}';
     }
 }
diff --git a/src/main/java/com/rappytv/globaltags/wrapper/model/ReferralLeaderboardEntry.java b/src/main/java/com/rappytv/globaltags/wrapper/model/ReferralLeaderboardEntry.java
new file mode 100644
index 0000000..56b47a2
--- /dev/null
+++ b/src/main/java/com/rappytv/globaltags/wrapper/model/ReferralLeaderboardEntry.java
@@ -0,0 +1,75 @@
+package com.rappytv.globaltags.wrapper.model;
+
+import java.util.UUID;
+
+/**
+ * A class representing an entry in the referral leaderboard
+ */
+public class ReferralLeaderboardEntry {
+
+    private final int rank;
+    private final UUID uuid;
+    private final int totalReferrals;
+    private final int currentMonthReferrals;
+
+    /**
+     * Creates a new entry in the referral leaderboard
+     *
+     * @param rank                  The rank of the entry
+     * @param uuid                  The UUID of the player
+     * @param totalReferrals        The total number of referrals
+     * @param currentMonthReferrals The number of referrals in the current month
+     */
+    public ReferralLeaderboardEntry(int rank, UUID uuid, int totalReferrals, int currentMonthReferrals) {
+        this.rank = rank;
+        this.uuid = uuid;
+        this.totalReferrals = totalReferrals;
+        this.currentMonthReferrals = currentMonthReferrals;
+    }
+
+    /**
+     * Gets the rank of the entry
+     *
+     * @return The rank
+     */
+    public int getRank() {
+        return this.rank;
+    }
+
+    /**
+     * Gets the UUID of the player
+     *
+     * @return The UUID
+     */
+    public UUID getUUID() {
+        return this.uuid;
+    }
+
+    /**
+     * Gets the total number of referrals
+     *
+     * @return The total number of referrals
+     */
+    public int getTotalReferrals() {
+        return this.totalReferrals;
+    }
+
+    /**
+     * Gets the number of referrals in the current month
+     *
+     * @return The number of referrals in the current month
+     */
+    public int getCurrentMonthReferrals() {
+        return this.currentMonthReferrals;
+    }
+
+    @Override
+    public String toString() {
+        return "ReferralLeaderboardEntry{" +
+                "rank=" + this.rank +
+                ", uuid=" + this.uuid +
+                ", totalReferrals=" + this.totalReferrals +
+                ", currentMonthReferrals=" + this.currentMonthReferrals +
+                '}';
+    }
+}
diff --git a/src/main/java/com/rappytv/globaltags/wrapper/model/TagHistoryEntry.java b/src/main/java/com/rappytv/globaltags/wrapper/model/TagHistoryEntry.java
index ed8dd48..2568b65 100644
--- a/src/main/java/com/rappytv/globaltags/wrapper/model/TagHistoryEntry.java
+++ b/src/main/java/com/rappytv/globaltags/wrapper/model/TagHistoryEntry.java
@@ -6,21 +6,31 @@
 
 /**
  * Represents an entry in the tag history, including the tag and a list of flagged words associated with it.
- *
- * @param tag the tag associated with this entry
- * @param flaggedWords the list of flagged words associated with this tag
  */
-public record TagHistoryEntry(@NotNull String tag, @NotNull List flaggedWords) {
+public class TagHistoryEntry {
+
+    private final String tag;
+    private final List flaggedWords;
+
+    /**
+     * Creates a new TagHistoryEntry instance.
+     *
+     * @param tag the tag associated with this entry
+     * @param flaggedWords the list of flagged words associated with this tag
+     */
+    public TagHistoryEntry(@NotNull String tag, @NotNull String[] flaggedWords) {
+        this.tag = tag;
+        this.flaggedWords = List.of(flaggedWords);
+    }
 
     /**
      * Retrieves the tag associated with this entry.
      *
      * @return the tag, never null
      */
-    @Override
     @NotNull
-    public String tag() {
-        return tag;
+    public String getTag() {
+        return this.tag;
     }
 
     /**
@@ -28,9 +38,8 @@ public String tag() {
      *
      * @return the list of flagged words, never null
      */
-    @Override
     @NotNull
-    public List flaggedWords() {
-        return flaggedWords;
+    public List getFlaggedWords() {
+        return this.flaggedWords;
     }
 }