diff --git a/minecord-bot/src/main/java/com/tisawesomeness/minecord/mc/external/MojangAPI.java b/minecord-bot/src/main/java/com/tisawesomeness/minecord/mc/external/MojangAPI.java index 31cb8c76..de755d87 100644 --- a/minecord-bot/src/main/java/com/tisawesomeness/minecord/mc/external/MojangAPI.java +++ b/minecord-bot/src/main/java/com/tisawesomeness/minecord/mc/external/MojangAPI.java @@ -1,22 +1,21 @@ package com.tisawesomeness.minecord.mc.external; import com.tisawesomeness.minecord.mc.player.Profile; +import com.tisawesomeness.minecord.mc.player.ProfileAction; import com.tisawesomeness.minecord.mc.player.SkinType; import com.tisawesomeness.minecord.mc.player.Username; import com.tisawesomeness.minecord.util.URLs; import com.tisawesomeness.minecord.util.UUIDs; - import lombok.NonNull; import lombok.extern.slf4j.Slf4j; +import org.json.JSONArray; import org.json.JSONObject; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import java.nio.charset.StandardCharsets; -import java.util.Base64; -import java.util.Optional; -import java.util.UUID; +import java.util.*; /** * A wrapper for the Mojang API. See the docs @@ -110,7 +109,10 @@ public Optional getProfile(@NonNull UUID uuid) throws IOException { } } - return Optional.of(new Profile(username, legacy, demo, skinType, skinUrl, capeUrl)); + JSONArray profileActionsArr = json.optJSONArray("profileActions"); + Set profileActions = parseProfileActions(profileActionsArr); + + return Optional.of(new Profile(username, legacy, demo, skinType, skinUrl, capeUrl, profileActions)); } private static SkinType getSkinType(@NonNull JSONObject skinObj) { @@ -127,4 +129,16 @@ private static String decodeBase64(@NonNull String base64String) { return new String(Base64.getDecoder().decode(base64String), StandardCharsets.UTF_8); } + private static Set parseProfileActions(JSONArray arr) { + if (arr == null) { + return Collections.emptySet(); + } + Set profileActions = EnumSet.noneOf(ProfileAction.class); + for (int i = 0; i < arr.length(); i++) { + String actionStr = arr.getString(i); + ProfileAction.from(actionStr.toUpperCase(Locale.ROOT)).ifPresent(profileActions::add); + } + return profileActions; + } + } diff --git a/minecord-bot/src/main/java/com/tisawesomeness/minecord/mc/player/Profile.java b/minecord-bot/src/main/java/com/tisawesomeness/minecord/mc/player/Profile.java index d17336c2..d73d46b2 100644 --- a/minecord-bot/src/main/java/com/tisawesomeness/minecord/mc/player/Profile.java +++ b/minecord-bot/src/main/java/com/tisawesomeness/minecord/mc/player/Profile.java @@ -1,16 +1,20 @@ package com.tisawesomeness.minecord.mc.player; +import lombok.AllArgsConstructor; import lombok.NonNull; import lombok.Value; import javax.annotation.Nullable; import java.net.URL; +import java.util.Collections; import java.util.Optional; +import java.util.Set; /** * Provides additional account information about a player. */ @Value +@AllArgsConstructor public class Profile { /** * The player's current username @@ -30,6 +34,12 @@ public class Profile { SkinType skinType; @Nullable URL skinUrl; @Nullable URL capeUrl; + Set profileActions; + + public Profile(@NonNull Username username, boolean legacy, boolean demo, SkinType skinType, @Nullable URL skinUrl, + @Nullable URL capeUrl) { + this(username, legacy, demo, skinType, skinUrl, capeUrl, Collections.emptySet()); + } /** * @return The skin URL, or empty if the player has no custom skin diff --git a/minecord-bot/src/main/java/com/tisawesomeness/minecord/mc/player/ProfileAction.java b/minecord-bot/src/main/java/com/tisawesomeness/minecord/mc/player/ProfileAction.java new file mode 100644 index 00000000..5ef356f3 --- /dev/null +++ b/minecord-bot/src/main/java/com/tisawesomeness/minecord/mc/player/ProfileAction.java @@ -0,0 +1,20 @@ +package com.tisawesomeness.minecord.mc.player; + +import lombok.NonNull; + +import java.util.Optional; + +/** A moderation action taken against a profile */ +public enum ProfileAction { + FORCED_NAME_CHANGE, + USING_BANNED_SKIN; + + public static Optional from(@NonNull String str) { + for (ProfileAction action : values()) { + if (action.toString().equals(str)) { + return Optional.of(action); + } + } + return Optional.empty(); + } +} diff --git a/minecord-bot/src/test/java/com/tisawesomeness/minecord/mc/external/MojangAPITest.java b/minecord-bot/src/test/java/com/tisawesomeness/minecord/mc/external/MojangAPITest.java index 0c078fc1..af148f4a 100644 --- a/minecord-bot/src/test/java/com/tisawesomeness/minecord/mc/external/MojangAPITest.java +++ b/minecord-bot/src/test/java/com/tisawesomeness/minecord/mc/external/MojangAPITest.java @@ -1,12 +1,13 @@ package com.tisawesomeness.minecord.mc.external; +import com.tisawesomeness.minecord.common.util.IO; import com.tisawesomeness.minecord.mc.player.Profile; +import com.tisawesomeness.minecord.mc.player.ProfileAction; import com.tisawesomeness.minecord.mc.player.SkinType; import com.tisawesomeness.minecord.mc.player.Username; import com.tisawesomeness.minecord.testutil.mc.MockMojangAPI; import com.tisawesomeness.minecord.util.URLs; import com.tisawesomeness.minecord.util.UUIDs; - import org.json.JSONArray; import org.json.JSONObject; import org.junit.jupiter.api.DisplayName; @@ -15,9 +16,7 @@ import java.io.IOException; import java.net.URL; import java.nio.charset.StandardCharsets; -import java.util.Base64; -import java.util.Optional; -import java.util.UUID; +import java.util.*; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; @@ -29,6 +28,7 @@ public class MojangAPITest { private static final Username NON_ASCII_USERNAME = new Username("ooθoo"); private static final UUID TESTING_UUID = UUID.fromString("f6489b79-7a9f-49e2-980e-265a05dbc3af"); private static final UUID FAKE_UUID = UUID.fromString("f6489b79-7a9f-49e2-980e-265a05dbc3ae"); + private static final String PROFILE_ACTIONS_RESPONSE = IO.loadResource("profileActionsTestResponse.json", MojangAPITest.class); @Test @DisplayName("Username-->uuid endpoint is parsed correctly") @@ -126,4 +126,15 @@ public void testNonExistentProfile() throws IOException { assertThat(api.getProfile(FAKE_UUID)).isEmpty(); } + @Test + @DisplayName("Profile actions are correctly parsed") + public void testProfileActions() throws IOException { + MockMojangAPI api = new MockMojangAPI(); + api.mapProfile(TESTING_UUID, PROFILE_ACTIONS_RESPONSE); + URL skinUrl = URLs.createUrl("https://textures.minecraft.net/texture/3196c893f1a6131ad5ba78fec26185bc424f408419e237f7b15f8a3bc69a90a0"); + Set profileActions = EnumSet.of(ProfileAction.FORCED_NAME_CHANGE, ProfileAction.USING_BANNED_SKIN); + Profile profile = new Profile(TESTING_USERNAME, false, false, SkinType.STEVE, skinUrl, null, profileActions); + assertThat(api.getProfile(TESTING_UUID)).contains(profile); + } + } diff --git a/minecord-bot/src/test/resources/profileActionsTestResponse.json b/minecord-bot/src/test/resources/profileActionsTestResponse.json new file mode 100644 index 00000000..38c03a1e --- /dev/null +++ b/minecord-bot/src/test/resources/profileActionsTestResponse.json @@ -0,0 +1,14 @@ +{ + "id": "f6489b797a9f49e2980e265a05dbc3af", + "name": "Tis_awesomeness", + "properties": [ + { + "name": "textures", + "value": "ewogICJ0aW1lc3RhbXAiIDogMTY5NDMwNTYxNTUyMiwKICAicHJvZmlsZUlkIiA6ICJmNjQ4OWI3OTdhOWY0OWUyOTgwZTI2NWEwNWRiYzNhZiIsCiAgInByb2ZpbGVOYW1lIiA6ICJUaXNfYXdlc29tZW5lc3MiLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMzE5NmM4OTNmMWE2MTMxYWQ1YmE3OGZlYzI2MTg1YmM0MjRmNDA4NDE5ZTIzN2Y3YjE1ZjhhM2JjNjlhOTBhMCIKICAgIH0KICB9Cn0=" + } + ], + "profileActions": [ + "FORCED_NAME_CHANGE", + "USING_BANNED_SKIN" + ] +} \ No newline at end of file