Cleanup
All checks were successful
Deploy API / deploy (ubuntu-latest, 2.44.0) (push) Successful in 54s

This commit is contained in:
Braydon 2024-09-10 15:13:30 -04:00
parent 4bb5554a71
commit 2d5890eacb
5 changed files with 138 additions and 91 deletions

@ -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<ConnectedAccount> fromJson(@NonNull JSONObject userJson) {
Set<ConnectedAccount> 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<String, String> metadata = new HashMap<>();
if (accountJson.has("metadata")) {
for (Map.Entry<String, Object> entry : accountJson.getJSONObject("metadata").toMap().entrySet()) {
metadata.put(entry.getKey(), entry.getValue().toString());
Map<String, String> metadata = new HashMap<>();
if (accountJson.has("metadata")) {
for (Map.Entry<String, Object> 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;
}
}

@ -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<Activity> 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;
}
}

@ -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.
* <p>
* A user is "legacy" if they haven't yet
* moved to the new username system and got
* rid of their discriminator.
* </p>
*/
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<ClientType> activeClients = member == null ? EnumSet.noneOf(ClientType.class) : member.getActiveClients();
// Get the user's activities
List<Activity> 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<UserBadge> 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<ConnectedAccount> 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)
);
}
}

@ -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<Activity> 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;
}
}

@ -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<UserBadge> fromJson(@NonNull JSONObject userJson) {
Set<UserBadge> 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;
}
}