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 2a5c9f3..2fbe488 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 @@ -3,6 +3,9 @@ package me.braydon.tether.model.user; import kong.unirest.core.json.JSONObject; import lombok.*; +import java.util.HashMap; +import java.util.Map; + /** * A linked connection to a {@link DiscordUser}. * @@ -25,6 +28,11 @@ public class ConnectedAccount { */ @NonNull private final String name; + /** + * The metadata for this account. + */ + @NonNull private final Map metadata; + /** * Whether this account is verified. */ @@ -41,7 +49,15 @@ public class ConnectedAccount { 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()); + } + } + boolean verified = accountJson.getBoolean("verified"); - return new ConnectedAccount(id, type, name, verified); + return new ConnectedAccount(id, type, name, metadata, verified); } } \ 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 7c6323e..4a57dd3 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 @@ -6,6 +6,7 @@ import lombok.*; import me.braydon.tether.common.DiscordUtils; import me.braydon.tether.model.user.avatar.Avatar; import me.braydon.tether.model.user.avatar.AvatarDecoration; +import me.braydon.tether.model.user.badge.UserBadge; import me.braydon.tether.model.user.clan.Clan; import me.braydon.tether.model.user.nitro.NitroSubscription; import net.dv8tion.jda.api.OnlineStatus; @@ -76,6 +77,11 @@ public final class DiscordUser { */ private final String bio; + /** + * The user's pronouns, if any. + */ + private final String pronouns; + /** * The accent color (hex) of this user. */ @@ -101,6 +107,11 @@ public final class DiscordUser { */ @EqualsAndHashCode.Exclude private final SpotifyActivity spotify; + /** + * The badges this user has. + */ + @NonNull private final Set badges; + /** * The connected accounts of this user. */ @@ -168,6 +179,12 @@ public final class DiscordUser { NitroSubscription nitroSubscription = userJson.isNull("premium_type") || userJson.isNull("premium_since") ? null : NitroSubscription.fromJson(userJson); + JSONObject profileJson = userJson.has("user_profile") ? userJson.getJSONObject("user_profile") : null; + String pronouns = null; + if (profileJson != null) { + pronouns = profileJson.optString("pronouns", null); + } + boolean bot = detailsJson.optBoolean("bot", false); long created = DiscordUtils.getTimeCreated(snowflake); @@ -191,20 +208,29 @@ public final class DiscordUser { } } + // 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 accounts = userJson.getJSONArray("connected_accounts"); - for (int i = 0; i < accounts.length(); i++) { - connectedAccounts.add(ConnectedAccount.fromJson(accounts.getJSONObject(i))); + 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, - accentColor, onlineStatus, activeClients, activities, spotify, connectedAccounts, clan, nitroSubscription, - bot, isUserLegacy, created + pronouns, accentColor, onlineStatus, activeClients, activities, spotify, badges, connectedAccounts, clan, + nitroSubscription, bot, isUserLegacy, created ); } } \ No newline at end of file diff --git a/API/src/main/java/me/braydon/tether/model/user/avatar/DecorationAsset.java b/API/src/main/java/me/braydon/tether/model/user/avatar/DecorationAsset.java index e946e1e..5421993 100644 --- a/API/src/main/java/me/braydon/tether/model/user/avatar/DecorationAsset.java +++ b/API/src/main/java/me/braydon/tether/model/user/avatar/DecorationAsset.java @@ -5,7 +5,7 @@ import lombok.*; import me.braydon.tether.model.user.DiscordUser; /** - * A {@link DiscordUser}'s avatar. + * The decoration for a {@link DiscordUser}'s {@link Avatar}. * * @author Braydon */ 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 new file mode 100644 index 0000000..7ddbf68 --- /dev/null +++ b/API/src/main/java/me/braydon/tether/model/user/badge/UserBadge.java @@ -0,0 +1,48 @@ +package me.braydon.tether.model.user.badge; + +import kong.unirest.core.json.JSONObject; +import lombok.*; +import me.braydon.tether.model.user.DiscordUser; + +/** + * A {@link DiscordUser}'s avatar. + * + * @author Braydon + */ +@AllArgsConstructor(access = AccessLevel.PRIVATE) @Getter @EqualsAndHashCode +public class UserBadge { + /** + * The id of this user badge. + */ + @NonNull private final String id; + + /** + * The description of this user badge. + */ + @NonNull private final String description; + + /** + * The icon of this user badge. + */ + @NonNull private final UserBadgeIcon icon; + + /** + * The link to this user badge, if any. + */ + private final String link; + + /** + * Construct a badge for a user. + * + * @param badgeJson the badge json + * @return the constructed user badge + */ + @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); + } +} \ No newline at end of file diff --git a/API/src/main/java/me/braydon/tether/model/user/badge/UserBadgeIcon.java b/API/src/main/java/me/braydon/tether/model/user/badge/UserBadgeIcon.java new file mode 100644 index 0000000..40afb3a --- /dev/null +++ b/API/src/main/java/me/braydon/tether/model/user/badge/UserBadgeIcon.java @@ -0,0 +1,37 @@ +package me.braydon.tether.model.user.badge; + +import kong.unirest.core.json.JSONObject; +import lombok.*; +import me.braydon.tether.model.user.DiscordUser; + +/** + * A {@link DiscordUser}'s avatar. + * + * @author Braydon + */ +@AllArgsConstructor(access = AccessLevel.PRIVATE) @Getter @EqualsAndHashCode +public class UserBadgeIcon { + private static final String BADGE_URL = "https://cdn.discordapp.com/badge-icons/%s.png"; + + /** + * The id of the user's badge. + */ + @NonNull private final String id; + + /** + * The URL of the user's badge. + */ + @NonNull private final String url; + + /** + * Construct a badge for a user. + * + * @param badgeJson the badge json + * @return the constructed user badge + */ + @NonNull + protected static UserBadgeIcon fromJson(@NonNull JSONObject badgeJson) { + String badgeId = badgeJson.getString("icon"); + return new UserBadgeIcon(badgeId, BADGE_URL.formatted(badgeId)); + } +} \ No newline at end of file diff --git a/API/src/main/java/me/braydon/tether/model/user/clan/Clan.java b/API/src/main/java/me/braydon/tether/model/user/clan/Clan.java index de38bc3..91f44af 100644 --- a/API/src/main/java/me/braydon/tether/model/user/clan/Clan.java +++ b/API/src/main/java/me/braydon/tether/model/user/clan/Clan.java @@ -24,7 +24,7 @@ public class Clan { /** * The badge for this clan. */ - @NonNull private final Badge badge; + @NonNull private final ClanBadge clanBadge; /** * Whether the identity is enabled for this clan. @@ -41,8 +41,8 @@ public class Clan { public static Clan fromJson(@NonNull JSONObject clanJson) { long snowflake = Long.parseLong(clanJson.getString("identity_guild_id")); String tag = clanJson.getString("tag"); - Badge badge = Badge.fromJson(snowflake, clanJson); + ClanBadge clanBadge = ClanBadge.fromJson(snowflake, clanJson); boolean identityEnabled = clanJson.getBoolean("identity_enabled"); - return new Clan(snowflake, tag, badge, identityEnabled); + return new Clan(snowflake, tag, clanBadge, identityEnabled); } } \ No newline at end of file diff --git a/API/src/main/java/me/braydon/tether/model/user/clan/Badge.java b/API/src/main/java/me/braydon/tether/model/user/clan/ClanBadge.java similarity index 71% rename from API/src/main/java/me/braydon/tether/model/user/clan/Badge.java rename to API/src/main/java/me/braydon/tether/model/user/clan/ClanBadge.java index aeb4e41..96652ac 100644 --- a/API/src/main/java/me/braydon/tether/model/user/clan/Badge.java +++ b/API/src/main/java/me/braydon/tether/model/user/clan/ClanBadge.java @@ -3,15 +3,14 @@ package me.braydon.tether.model.user.clan; import kong.unirest.core.json.JSONObject; import lombok.*; import me.braydon.tether.common.DiscordUtils; -import me.braydon.tether.model.user.DiscordUser; /** - * A {@link DiscordUser}'s avatar. + * A {@link Clan}'s badge. * * @author Braydon */ @AllArgsConstructor(access = AccessLevel.PRIVATE) @Getter @EqualsAndHashCode -public class Badge { +public class ClanBadge { private static final String CLAN_BADGE_URL = "https://cdn.discordapp.com/clan-badges/%s/%s.%s"; /** @@ -32,8 +31,8 @@ public class Badge { * @return the constructed clan badge */ @NonNull - protected static Badge fromJson(long userSnowflake, @NonNull JSONObject clanJson) { + protected static ClanBadge fromJson(long userSnowflake, @NonNull JSONObject clanJson) { String badgeId = clanJson.getString("badge"); - return new Badge(badgeId, CLAN_BADGE_URL.formatted(userSnowflake, badgeId, DiscordUtils.getMediaExtension(badgeId))); + return new ClanBadge(badgeId, CLAN_BADGE_URL.formatted(userSnowflake, badgeId, DiscordUtils.getMediaExtension(badgeId))); } } \ No newline at end of file