Skip to content

Commit 9f6ef33

Browse files
Merge remote-tracking branch 'origin/master'
# Conflicts: # src/main/java/net/modgarden/gardenbot/commands/event/UnsubmitHandler.java # src/main/java/net/modgarden/gardenbot/interaction/response/EmbedResponse.java
2 parents 7ac378a + e063615 commit 9f6ef33

18 files changed

+418
-57
lines changed

src/main/java/net/modgarden/gardenbot/GardenBotButtonHandlers.java

Lines changed: 53 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,10 @@
77
import net.modgarden.gardenbot.interaction.ButtonInteraction;
88
import net.modgarden.gardenbot.interaction.button.ButtonDispatcher;
99
import net.modgarden.gardenbot.interaction.response.EmbedResponse;
10+
import net.modgarden.gardenbot.interaction.response.MessageResponse;
1011
import net.modgarden.gardenbot.interaction.response.ModalResponse;
1112
import net.modgarden.gardenbot.interaction.response.Response;
13+
import net.modgarden.gardenbot.util.MinecraftAccountUtil;
1214
import net.modgarden.gardenbot.util.ModGardenAPIClient;
1315

1416
import java.io.IOException;
@@ -21,6 +23,8 @@ public class GardenBotButtonHandlers {
2123
public static void registerAll() {
2224
ButtonDispatcher.register("linkModrinth", new ModalResponse(GardenBotModals.LINK_MODRINTH));
2325
ButtonDispatcher.register("unlinkModrinth", GardenBotButtonHandlers::unlinkModrinth);
26+
ButtonDispatcher.register("linkMinecraft", new ModalResponse(GardenBotModals.LINK_MINECRAFT));
27+
ButtonDispatcher.register("unlinkMinecraft?%s", GardenBotButtonHandlers::unlinkMinecraft);
2428
}
2529

2630
public static Response unlinkModrinth(ButtonInteraction interaction) {
@@ -35,7 +39,6 @@ public static Response unlinkModrinth(ButtonInteraction interaction) {
3539
"discord/unlink",
3640
HttpRequest.BodyPublishers.ofString(inputJson.toString()),
3741
HttpResponse.BodyHandlers.ofInputStream(),
38-
"Authorization", "Basic " + GardenBot.DOTENV.get("OAUTH_SECRET"),
3942
"Content-Type", "application/json"
4043
);
4144
if (stream.statusCode() < 200 || stream.statusCode() > 299) {
@@ -44,7 +47,7 @@ public static Response unlinkModrinth(ButtonInteraction interaction) {
4447
json.getAsJsonObject().getAsJsonPrimitive("description").getAsString() :
4548
"Undefined Error.";
4649
return new EmbedResponse()
47-
.setTitle("Encountered an exception whilst attempting to unlink your Mod Garden account from Modrinth.")
50+
.setTitle("Encountered an exception whilst attempting to unlink your Modrinth from your Mod Garden account.")
4851
.setDescription(stream.statusCode() + ": " + errorDescription + "\nPlease report this to a team member.")
4952
.setColor(0xFF0000)
5053
.markEphemeral();
@@ -58,4 +61,52 @@ public static Response unlinkModrinth(ButtonInteraction interaction) {
5861
.setColor(0xA9FFA7)
5962
.markEphemeral();
6063
}
64+
65+
public static Response unlinkMinecraft(ButtonInteraction interaction) {
66+
User user = interaction.event().getUser();
67+
String uuid = interaction.arguments()[0];
68+
69+
JsonObject inputJson = new JsonObject();
70+
inputJson.addProperty("discord_id", user.getId());
71+
inputJson.addProperty("service", "minecraft");
72+
inputJson.addProperty("minecraft_uuid", uuid);
73+
74+
try {
75+
HttpResponse<InputStream> stream = ModGardenAPIClient.post(
76+
"discord/unlink",
77+
HttpRequest.BodyPublishers.ofString(inputJson.toString()),
78+
HttpResponse.BodyHandlers.ofInputStream(),
79+
"Content-Type", "application/json"
80+
);
81+
if (stream.statusCode() < 200 || stream.statusCode() > 299) {
82+
JsonElement json = JsonParser.parseReader(new InputStreamReader(stream.body()));
83+
String errorDescription = json.isJsonObject() && json.getAsJsonObject().has("description") ?
84+
json.getAsJsonObject().getAsJsonPrimitive("description").getAsString() :
85+
"Undefined Error.";
86+
return new EmbedResponse()
87+
.setTitle("Encountered an exception whilst attempting to unlink your Minecraft account from your Mod Garden account.")
88+
.setDescription(stream.statusCode() + ": " + errorDescription + "\nPlease report this to a team member.")
89+
.setColor(0xFF0000)
90+
.markEphemeral();
91+
}
92+
if (stream.statusCode() == 200) {
93+
return new MessageResponse()
94+
.setMessage("You already .")
95+
.markEphemeral();
96+
}
97+
} catch (IOException | InterruptedException ex) {
98+
GardenBot.LOG.error("", ex);
99+
}
100+
101+
String username = MinecraftAccountUtil.getMinecraftUsernameFromUuid(uuid);
102+
if (username == null) {
103+
username = uuid;
104+
}
105+
106+
return new EmbedResponse()
107+
.setTitle("Successfully unlinked your Minecraft account (" + username + ") from Mod Garden!")
108+
.setColor(0xA9FFA7)
109+
.markEphemeral();
110+
111+
}
61112
}

src/main/java/net/modgarden/gardenbot/GardenBotCommands.java

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,29 @@ public static void registerAll() {
1818
"create",
1919
"Registers a Mod Garden account for yourself.", CreateCommandHandler::handleAccountCreation
2020
)));
21-
SlashCommandDispatcher.register(new SlashCommand("link", "Link your account with different services.",
21+
SlashCommandDispatcher.register(new SlashCommand("link", "Link different services to your Mod Garden account.",
2222
new SlashCommand.SubCommand(
2323
"modrinth",
24-
"Provides setup to link your account with Modrinth",
24+
"Provides setup to link your Modrinth account",
2525
LinkCommandHandler::handleModrinthLink
26+
),
27+
new SlashCommand.SubCommand(
28+
"minecraft",
29+
"Provides setup to link your Minecraft account",
30+
LinkCommandHandler::handleMinecraftLink
2631
)));
27-
SlashCommandDispatcher.register(new SlashCommand("unlink", "Unlink your account from different services.",
32+
SlashCommandDispatcher.register(new SlashCommand("unlink", "Unlink different services from your Mod Garden account.",
2833
new SlashCommand.SubCommand(
2934
"modrinth",
30-
"Unlinks your account from Modrinth",
35+
"Unlinks your Modrinth account from Mod Garden",
3136
UnlinkCommandHandler::handleModrinthUnlink
37+
),
38+
new SlashCommand.SubCommand(
39+
"minecraft",
40+
"Unlinks your Minecraft account(s) from Mod Garden",
41+
UnlinkCommandHandler::handleMinecraftUnlink,
42+
UnlinkCommandHandler::getMinecraftChoices,
43+
new SlashCommandOption(OptionType.STRING, "account", "The username of the Minecraft account to unlink.", true, true)
3244
)));
3345

3446
SlashCommandDispatcher.register(new SlashCommand("profile", "Actions relating to your visible Mod Garden profile.",

src/main/java/net/modgarden/gardenbot/GardenBotEvents.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ public void onCommandAutoCompleteInteraction(@NotNull CommandAutoCompleteInterac
4444

4545
@Override
4646
public void onButtonInteraction(@NotNull ButtonInteractionEvent event) {
47-
var response = ButtonDispatcher.dispatch(new ButtonInteraction(event));
47+
var response = ButtonDispatcher.dispatch(event);
4848
response.send(event).queue();
4949
}
5050

src/main/java/net/modgarden/gardenbot/GardenBotModals.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package net.modgarden.gardenbot;
22

3+
import net.modgarden.gardenbot.modals.account.LinkMinecraftModal;
34
import net.modgarden.gardenbot.modals.account.LinkModrinthModal;
45
import net.modgarden.gardenbot.modals.account.RegisterModal;
56

@@ -8,4 +9,5 @@
89
public class GardenBotModals {
910
public static final RegisterModal REGISTER = register(new RegisterModal());
1011
public static final LinkModrinthModal LINK_MODRINTH = register(new LinkModrinthModal());
12+
public static final LinkMinecraftModal LINK_MINECRAFT = register(new LinkMinecraftModal());
1113
}

src/main/java/net/modgarden/gardenbot/commands/account/LinkCommandHandler.java

Lines changed: 46 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
import java.io.InputStreamReader;
1818
import java.net.URI;
1919
import java.net.http.HttpResponse;
20+
import java.nio.charset.StandardCharsets;
21+
import java.util.Scanner;
2022

2123
public class LinkCommandHandler {
2224
public static Response handleModrinthLink(SlashCommandInteraction interaction) {
@@ -34,7 +36,7 @@ public static Response handleModrinthLink(SlashCommandInteraction interaction) {
3436
return new MessageResponse()
3537
.setMessage("You do not have a Mod Garden account.\nPlease create one with **/account create**.")
3638
.markEphemeral();
37-
} else {
39+
} else if (stream.statusCode() < 200 && stream.statusCode() > 299) {
3840
JsonElement json = JsonParser.parseReader(new InputStreamReader(stream.body()));
3941
String errorDescription = json.isJsonObject() && json.getAsJsonObject().has("description") ?
4042
json.getAsJsonObject().getAsJsonPrimitive("description").getAsString() :
@@ -52,8 +54,12 @@ public static Response handleModrinthLink(SlashCommandInteraction interaction) {
5254
return new EmbedResponse()
5355
.setTitle("Link your Modrinth Account!")
5456
.setDescription(
55-
"1. Authorize with Modrinth, which will redirect you to a page with a link code.\n" +
56-
"2. Enter your link code inside the modal.")
57+
"""
58+
1. Authorize with Modrinth, which will redirect you to a page with a link code.
59+
2. 2. Enter your link code inside the modal.
60+
61+
You may only have one Modrinth account linked to your Mod Garden account.
62+
""")
5763
.setColor(0xA9FFA7)
5864
.addButtonUrl(
5965
URI.create("https://modrinth.com/auth/authorize?client_id=Q2tuKyb4&redirect_uri=" + GardenBot.API_URL + "discord/oauth/modrinth&scope=USER_READ+PROJECT_READ+VERSION_READ+ORGANIZATION_READ"),
@@ -70,36 +76,58 @@ public static Response handleModrinthLink(SlashCommandInteraction interaction) {
7076

7177

7278
public static Response handleMinecraftLink(SlashCommandInteraction interaction) {
79+
interaction.event().deferReply(true).queue();
7380
User user = interaction.event().getUser();
81+
String challengeCode = null;
7482

7583
try {
76-
HttpResponse<InputStream> stream = ModGardenAPIClient.get("user/" + user.getId() + "?service=discord", HttpResponse.BodyHandlers.ofInputStream());
77-
if (stream.statusCode() == 404) {
84+
HttpResponse<InputStream> userResponse = ModGardenAPIClient.get("user/" + user.getId() + "?service=discord", HttpResponse.BodyHandlers.ofInputStream());
85+
if (userResponse.statusCode() == 404) {
7886
return new MessageResponse()
7987
.setMessage("You do not have a Mod Garden account.\nPlease create one with **/account create**.");
80-
} else if (stream.statusCode() != 200) {
81-
JsonElement json = JsonParser.parseReader(new InputStreamReader(stream.body()));
82-
String errorDescription = json.isJsonObject() && json.getAsJsonObject().has("description") ?
83-
json.getAsJsonObject().getAsJsonPrimitive("description").getAsString() :
84-
"Undefined Error.";
85-
return new EmbedResponse()
86-
.setTitle("Encountered an exception whilst attempting to send the setup for linking your Minecraft account to your Mod Garden account.")
87-
.setDescription(stream.statusCode() + ": " + errorDescription + "\nPlease report this to a team member.")
88-
.setColor(0xFF0000)
89-
.markEphemeral();
88+
} else if (userResponse.statusCode() != 200) {
89+
try (var userStream = new InputStreamReader(userResponse.body())) {
90+
JsonElement json = JsonParser.parseReader(userStream);
91+
String errorDescription = json.isJsonObject() && json.getAsJsonObject().has("description") ?
92+
json.getAsJsonObject().getAsJsonPrimitive("description").getAsString() :
93+
"Undefined Error.";
94+
return new EmbedResponse()
95+
.setTitle("Encountered an exception whilst attempting to send the setup for linking your Minecraft account to your Mod Garden account.")
96+
.setDescription(userResponse.statusCode() + ": " + errorDescription + "\nPlease report this to a team member.")
97+
.setColor(0xFF0000)
98+
.markEphemeral();
99+
}
100+
}
101+
102+
HttpResponse<InputStream> challengeCodeResponse = ModGardenAPIClient.get("discord/oauth/minecraft/challenge", HttpResponse.BodyHandlers.ofInputStream());
103+
try (var challengeCodeStream = new InputStreamReader(challengeCodeResponse.body(), StandardCharsets.UTF_8)) {
104+
challengeCode = new Scanner(challengeCodeStream).next();
90105
}
91106
} catch (IOException | InterruptedException ex) {
92107
GardenBot.LOG.error("", ex);
93108
}
94109

110+
if (challengeCode == null) {
111+
return new EmbedResponse()
112+
.setTitle("Encountered an exception whilst attempting to send the setup for linking your Minecraft account to your Mod Garden account.")
113+
.setDescription("Failed to create challenge code for Microsoft Authentication.\nPlease report this to a team member.")
114+
.setColor(0xFF0000)
115+
.markEphemeral();
116+
}
117+
95118
return new EmbedResponse()
96119
.setTitle("Link your Minecraft Account!")
97120
.setDescription(
98-
"1. Authorize with Microsoft, which will redirect you to a page with a link code.\n" +
99-
"2. Enter your link code inside the modal.")
121+
"""
122+
1. Authorize with Microsoft, which will redirect you to a page with a link code.
123+
2. Enter your link code inside the modal.
124+
125+
You may have multiple Minecraft accounts linked to your Mod Garden account.
126+
You are only able to use each Microsoft Authorization link once. Please generate a new message if you need another one.
127+
""")
100128
.setColor(0xA9FFA7)
101129
.addButtonUrl(
102-
URI.create("https://login.microsoftonline.com/consumers/oauth2/v2.0/authorize?client_id=5023fb8b-017e-497a-82af-de70b3b754f0&response_type=code&redirect_uri=" + GardenBot.API_URL + "discord/oauth/minecraft&scope=XboxLive.signin api.minecraftservices.com"),
130+
URI.create("https://login.microsoftonline.com/consumers/oauth2/v2.0/authorize?client_id=e7ee42f6-e542-4ce6-9f7b-1d31941e84c6&response_type=code&redirect_uri=" + GardenBot.API_URL.replaceAll(":", "%3A").replaceAll("/", "%2F") + "discord%2Foauth%2Fminecraft&response_mode=query&scope=XboxLive.signIn&state=" + challengeCode + "&prompt=select_account&code_challenge=" + challengeCode + "&code_challenge_method=S256"),
103131
"1. Authorize",
104132
Emoji.fromCustom("microsoft", 1360176270687731842L, false)
105133
)

src/main/java/net/modgarden/gardenbot/commands/account/ProfileCommandHandler.java

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,6 @@ public static Response handleModifyUsername(SlashCommandInteraction interaction)
5454
"discord/modify/username",
5555
HttpRequest.BodyPublishers.ofString(inputJson.toString()),
5656
HttpResponse.BodyHandlers.ofInputStream(),
57-
"Authorization", "Basic " + GardenBot.DOTENV.get("OAUTH_SECRET"),
5857
"Content-Type", "application/json"
5958
);
6059
if (postStream.statusCode() < 200 || postStream.statusCode() > 299) {
@@ -125,7 +124,6 @@ public static Response handleModifyDisplayName(SlashCommandInteraction interacti
125124
"discord/modify/displayname",
126125
HttpRequest.BodyPublishers.ofString(inputJson.toString()),
127126
HttpResponse.BodyHandlers.ofInputStream(),
128-
"Authorization", "Basic " + GardenBot.DOTENV.get("OAUTH_SECRET"),
129127
"Content-Type", "application/json"
130128
);
131129
if (postStream.statusCode() < 200 || postStream.statusCode() > 299) {
@@ -196,7 +194,6 @@ public static Response handleModifyPronouns(SlashCommandInteraction interaction)
196194
"discord/modify/pronouns",
197195
HttpRequest.BodyPublishers.ofString(inputJson.toString()),
198196
HttpResponse.BodyHandlers.ofInputStream(),
199-
"Authorization", "Basic " + GardenBot.DOTENV.get("OAUTH_SECRET"),
200197
"Content-Type", "application/json"
201198
);
202199
if (postStream.statusCode() < 200 || postStream.statusCode() > 299) {
@@ -265,7 +262,6 @@ public static Response removePronouns(SlashCommandInteraction interaction) {
265262
"discord/remove/pronouns",
266263
HttpRequest.BodyPublishers.ofString(inputJson.toString()),
267264
HttpResponse.BodyHandlers.ofInputStream(),
268-
"Authorization", "Basic " + GardenBot.DOTENV.get("OAUTH_SECRET"),
269265
"Content-Type", "application/json"
270266
);
271267
if (postStream.statusCode() < 200 || postStream.statusCode() > 299) {

0 commit comments

Comments
 (0)