From 2d5890eacb8fd4c3b20ed35264408ef83b178163 Mon Sep 17 00:00:00 2001 From: Rainnny7 Date: Tue, 10 Sep 2024 15:13:30 -0400 Subject: [PATCH] Cleanup --- .../tether/model/user/ConnectedAccount.java | 39 ++++++---- .../tether/model/user/CustomStatus.java | 45 +++++++++++ .../tether/model/user/DiscordUser.java | 75 ++++++------------- .../tether/model/user/SpotifyActivity.java | 39 ++++++---- .../tether/model/user/badge/UserBadge.java | 31 +++++--- 5 files changed, 138 insertions(+), 91 deletions(-) create mode 100644 API/src/main/java/me/braydon/tether/model/user/CustomStatus.java diff --git a/API/src/main/java/me/braydon/tether/model/user/ConnectedAccount.java b/API/src/main/java/me/braydon/tether/model/user/ConnectedAccount.java index 2fbe488..c9739d0 100644 --- a/API/src/main/java/me/braydon/tether/model/user/ConnectedAccount.java +++ b/API/src/main/java/me/braydon/tether/model/user/ConnectedAccount.java @@ -1,10 +1,13 @@ package me.braydon.tether.model.user; +import kong.unirest.core.json.JSONArray; import kong.unirest.core.json.JSONObject; import lombok.*; import java.util.HashMap; +import java.util.HashSet; import java.util.Map; +import java.util.Set; /** * A linked connection to a {@link DiscordUser}. @@ -39,25 +42,33 @@ public class ConnectedAccount { private final boolean verified; /** - * Construct a connected account for a user. + * Construct the connected accounts for a user. * - * @param accountJson the connected account json - * @return the constructed account + * @param userJson the user's json + * @return the constructed accounts */ @NonNull - protected static ConnectedAccount fromJson(@NonNull JSONObject accountJson) { - String id = accountJson.getString("id"); - String type = accountJson.getString("type"); - String name = accountJson.getString("name"); + public static Set fromJson(@NonNull JSONObject userJson) { + Set connectedAccounts = new HashSet<>(); + if (userJson.has("connected_accounts")) { + JSONArray accountsArray = userJson.getJSONArray("connected_accounts"); + for (int i = 0; i < accountsArray.length(); i++) { + JSONObject accountJson = accountsArray.getJSONObject(i); + String id = accountJson.getString("id"); + String type = accountJson.getString("type"); + String name = accountJson.getString("name"); - Map metadata = new HashMap<>(); - if (accountJson.has("metadata")) { - for (Map.Entry entry : accountJson.getJSONObject("metadata").toMap().entrySet()) { - metadata.put(entry.getKey(), entry.getValue().toString()); + Map metadata = new HashMap<>(); + if (accountJson.has("metadata")) { + for (Map.Entry entry : accountJson.getJSONObject("metadata").toMap().entrySet()) { + metadata.put(entry.getKey(), entry.getValue().toString()); + } + } + + boolean verified = accountJson.getBoolean("verified"); + connectedAccounts.add(new ConnectedAccount(id, type, name, metadata, verified)); } } - - boolean verified = accountJson.getBoolean("verified"); - return new ConnectedAccount(id, type, name, metadata, verified); + return connectedAccounts; } } \ No newline at end of file diff --git a/API/src/main/java/me/braydon/tether/model/user/CustomStatus.java b/API/src/main/java/me/braydon/tether/model/user/CustomStatus.java new file mode 100644 index 0000000..0598aa3 --- /dev/null +++ b/API/src/main/java/me/braydon/tether/model/user/CustomStatus.java @@ -0,0 +1,45 @@ +package me.braydon.tether.model.user; + +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NonNull; +import net.dv8tion.jda.api.entities.Activity; +import net.dv8tion.jda.api.entities.emoji.EmojiUnion; + +import java.util.List; + +/** + * The custom status of a {@link DiscordUser}. + * + * @author Braydon + */ +@AllArgsConstructor(access = AccessLevel.PRIVATE) @Getter +public class CustomStatus { + /** + * The value of this status. + */ + @NonNull private final String value; + + /** + * The unicode emoji for this status. + */ + private final String emoji; + + /** + * Construct a custom status for a user. + * + * @param activities the user's activities + * @return the constructed status, null if none + */ + protected static CustomStatus fromActivities(@NonNull List activities) { + for (Activity activity : activities) { + if (activity.getType() != Activity.ActivityType.CUSTOM_STATUS) { + continue; + } + EmojiUnion emoji = activity.getEmoji(); + return new CustomStatus(activity.getName(), emoji == null ? null : emoji.asUnicode().getFormatted()); + } + return null; + } +} \ No newline at end of file diff --git a/API/src/main/java/me/braydon/tether/model/user/DiscordUser.java b/API/src/main/java/me/braydon/tether/model/user/DiscordUser.java index aa36c25..9168fef 100644 --- a/API/src/main/java/me/braydon/tether/model/user/DiscordUser.java +++ b/API/src/main/java/me/braydon/tether/model/user/DiscordUser.java @@ -1,6 +1,5 @@ package me.braydon.tether.model.user; -import kong.unirest.core.json.JSONArray; import kong.unirest.core.json.JSONObject; import lombok.*; import me.braydon.tether.common.DiscordUtils; @@ -14,7 +13,10 @@ import net.dv8tion.jda.api.entities.Activity; import net.dv8tion.jda.api.entities.ClientType; import net.dv8tion.jda.api.entities.Member; -import java.util.*; +import java.util.Collections; +import java.util.EnumSet; +import java.util.List; +import java.util.Set; /** * A model of a Discord user. @@ -37,6 +39,11 @@ public final class DiscordUser { */ @NonNull private final String username; + /** + * This user's legacy username, if any. + */ + private final String legacyUsername; + /** * The display name of this user, if any. */ @@ -72,6 +79,11 @@ public final class DiscordUser { */ private final String bannerColor; + /** + * The custom status of this user, if any. + */ + private final CustomStatus customStatus; + /** * The user's bio, if any. */ @@ -132,16 +144,6 @@ public final class DiscordUser { */ private final boolean bot; - /** - * Whether this user is a legacy user. - *

- * A user is "legacy" if they haven't yet - * moved to the new username system and got - * rid of their discriminator. - *

- */ - private final boolean legacy; - /** * The unix time of when this user joined Discord. */ @@ -160,17 +162,11 @@ public final class DiscordUser { JSONObject detailsJson = userJson.has("user") ? userJson.getJSONObject("user") : userJson; long snowflake = Long.parseLong(detailsJson.getString("id")); - String username = detailsJson.getString("username"); - String displayName = detailsJson.optString("global_name", null); + String legacyUsername = userJson.optString("legacy_username", null); int discriminator = Integer.parseInt(detailsJson.getString("discriminator")); - boolean isUserLegacy = discriminator > 0; - UserFlags flags = UserFlags.fromJson(detailsJson); - Avatar avatar = Avatar.fromJson(snowflake, discriminator, isUserLegacy, detailsJson); AvatarDecoration avatarDecoration = detailsJson.isNull("avatar_decoration_data") ? null : AvatarDecoration.fromJson(detailsJson.getJSONObject("avatar_decoration_data")); - Banner banner = Banner.fromJson(snowflake, detailsJson); - String bannerColor = detailsJson.optString("banner_color", null); String bio = detailsJson.optString("bio", null); if (bio != null && (bio = bio.trim()).isEmpty()) { @@ -191,50 +187,23 @@ public final class DiscordUser { } } - boolean bot = detailsJson.optBoolean("bot", false); - long created = DiscordUtils.getTimeCreated(snowflake); - // Get the user's online status OnlineStatus onlineStatus = member == null ? OnlineStatus.OFFLINE : member.getOnlineStatus(); if (onlineStatus == OnlineStatus.UNKNOWN) { onlineStatus = OnlineStatus.OFFLINE; } - // Get the user's active clients and activities - EnumSet activeClients = member == null ? EnumSet.noneOf(ClientType.class) : member.getActiveClients(); + // Get the user's activities List activities = member == null ? Collections.emptyList() : member.getActivities(); - SpotifyActivity spotify = null; - for (Activity activity : activities) { - if (!activity.getName().equals("Spotify") || !activity.isRich()) { - continue; - } - spotify = SpotifyActivity.fromActivity(Objects.requireNonNull(activity.asRichPresence())); - break; - } - - // Get the user's badges - Set badges = new HashSet<>(); - if (userJson.has("badges")) { - JSONArray badgesArray = userJson.getJSONArray("badges"); - for (int i = 0; i < badgesArray.length(); i++) { - badges.add(UserBadge.fromJson(badgesArray.getJSONObject(i))); - } - } - - // Get the user's connected accounts - Set connectedAccounts = new HashSet<>(); - if (userJson.has("connected_accounts")) { - JSONArray accountsArray = userJson.getJSONArray("connected_accounts"); - for (int i = 0; i < accountsArray.length(); i++) { - connectedAccounts.add(ConnectedAccount.fromJson(accountsArray.getJSONObject(i))); - } - } // Finally return the constructed user return new DiscordUser( - snowflake, username, displayName, discriminator, flags, avatar, avatarDecoration, banner, bannerColor, bio, - pronouns, accentColor, onlineStatus, activeClients, activities, spotify, badges, connectedAccounts, clan, - nitroSubscription, bot, isUserLegacy, created + snowflake, detailsJson.getString("username"), legacyUsername, detailsJson.optString("global_name", null), + discriminator, UserFlags.fromJson(detailsJson), Avatar.fromJson(snowflake, discriminator, legacyUsername != null, detailsJson), avatarDecoration, + Banner.fromJson(snowflake, detailsJson), detailsJson.optString("banner_color", null), CustomStatus.fromActivities(activities), + bio, pronouns, accentColor, onlineStatus, member == null ? EnumSet.noneOf(ClientType.class) : member.getActiveClients(), activities, + SpotifyActivity.fromActivities(activities), UserBadge.fromJson(userJson), ConnectedAccount.fromJson(userJson), clan, nitroSubscription, + detailsJson.optBoolean("bot", false), DiscordUtils.getTimeCreated(snowflake) ); } } \ No newline at end of file diff --git a/API/src/main/java/me/braydon/tether/model/user/SpotifyActivity.java b/API/src/main/java/me/braydon/tether/model/user/SpotifyActivity.java index a763646..9841951 100644 --- a/API/src/main/java/me/braydon/tether/model/user/SpotifyActivity.java +++ b/API/src/main/java/me/braydon/tether/model/user/SpotifyActivity.java @@ -4,8 +4,10 @@ import lombok.AccessLevel; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NonNull; +import net.dv8tion.jda.api.entities.Activity; import net.dv8tion.jda.api.entities.RichPresence; +import java.util.List; import java.util.Objects; /** @@ -69,24 +71,31 @@ public class SpotifyActivity { /** * Construct a Spotify activity for a user. * - * @param richPresence the raw Discord data - * @return the constructed activity + * @param activities the user's activities + * @return the constructed activity, null if none */ - @NonNull @SuppressWarnings("DataFlowIssue") - protected static SpotifyActivity fromActivity(@NonNull RichPresence richPresence) { - String trackUrl = "https://open.spotify.com/track/" + richPresence.getSyncId(); + @SuppressWarnings("DataFlowIssue") + protected static SpotifyActivity fromActivities(@NonNull List activities) { + for (Activity activity : activities) { + if (!activity.getName().equals("Spotify") || !activity.isRich()) { + continue; + } + RichPresence richPresence = activity.asRichPresence(); + String trackUrl = "https://open.spotify.com/track/" + richPresence.getSyncId(); - // Track progress - long started = Objects.requireNonNull(richPresence.getTimestamps()).getStart(); - long ends = richPresence.getTimestamps().getEnd(); + // Track progress + long started = Objects.requireNonNull(richPresence.getTimestamps()).getStart(); + long ends = richPresence.getTimestamps().getEnd(); - long trackLength = ends - started; - long trackProgress = Math.min(System.currentTimeMillis() - started, trackLength); + long trackLength = ends - started; + long trackProgress = Math.min(System.currentTimeMillis() - started, trackLength); - return new SpotifyActivity( - richPresence.getSyncId(), richPresence.getDetails(), richPresence.getState().replace(";", ","), - richPresence.getLargeImage().getText(), richPresence.getLargeImage().getUrl(), trackUrl, trackProgress, - trackLength, started, ends - ); + return new SpotifyActivity( + richPresence.getSyncId(), richPresence.getDetails(), richPresence.getState().replace(";", ","), + richPresence.getLargeImage().getText(), richPresence.getLargeImage().getUrl(), trackUrl, trackProgress, + trackLength, started, ends + ); + } + return null; } } \ No newline at end of file diff --git a/API/src/main/java/me/braydon/tether/model/user/badge/UserBadge.java b/API/src/main/java/me/braydon/tether/model/user/badge/UserBadge.java index 7ddbf68..26cf0b3 100644 --- a/API/src/main/java/me/braydon/tether/model/user/badge/UserBadge.java +++ b/API/src/main/java/me/braydon/tether/model/user/badge/UserBadge.java @@ -1,9 +1,13 @@ package me.braydon.tether.model.user.badge; +import kong.unirest.core.json.JSONArray; import kong.unirest.core.json.JSONObject; import lombok.*; import me.braydon.tether.model.user.DiscordUser; +import java.util.HashSet; +import java.util.Set; + /** * A {@link DiscordUser}'s avatar. * @@ -32,17 +36,26 @@ public class UserBadge { private final String link; /** - * Construct a badge for a user. + * Construct the badges for a user. * - * @param badgeJson the badge json - * @return the constructed user badge + * @param userJson the user's json + * @return the constructed badges */ @NonNull - public static UserBadge fromJson(@NonNull JSONObject badgeJson) { - String id = badgeJson.getString("id"); - String description = badgeJson.getString("description"); - UserBadgeIcon icon = UserBadgeIcon.fromJson(badgeJson); - String link = badgeJson.optString("link", null); - return new UserBadge(id, description, icon, link); + public static Set fromJson(@NonNull JSONObject userJson) { + Set badges = new HashSet<>(); + if (!userJson.has("badges")) { + return badges; + } + JSONArray badgesArray = userJson.getJSONArray("badges"); + for (int i = 0; i < badgesArray.length(); i++) { + JSONObject badgeJson = badgesArray.getJSONObject(i); + String id = badgeJson.getString("id"); + String description = badgeJson.getString("description"); + UserBadgeIcon icon = UserBadgeIcon.fromJson(badgeJson); + String link = badgeJson.optString("link", null); + badges.add(new UserBadge(id, description, icon, link)); + } + return badges; } } \ No newline at end of file