Skip to content

Commit f7d9f9c

Browse files
committed
feat: add image upload support for 1.17.1
1 parent eddf9b1 commit f7d9f9c

5 files changed

Lines changed: 99 additions & 12 deletions

File tree

fabric-1.17/src/main/java/net/azisaba/interchatmod/fabric/Commands.java

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,23 @@
11
package net.azisaba.interchatmod.fabric;
22

3+
import com.google.gson.Gson;
4+
import com.google.gson.JsonObject;
35
import com.mojang.brigadier.arguments.StringArgumentType;
46
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
57
import net.azisaba.interchatmod.common.model.Guild;
68
import net.azisaba.interchatmod.common.model.GuildMember;
79
import net.azisaba.interchatmod.common.util.Constants;
810
import net.fabricmc.fabric.api.client.command.v1.FabricClientCommandSource;
11+
import net.minecraft.client.MinecraftClient;
912
import net.minecraft.command.CommandSource;
1013
import net.minecraft.text.*;
1114
import net.minecraft.util.Formatting;
1215
import org.jetbrains.annotations.NotNull;
1316

17+
import java.io.File;
18+
import java.io.IOException;
19+
import java.net.URISyntaxException;
20+
import java.nio.file.Files;
1421
import java.util.*;
1522
import java.util.function.Consumer;
1623
import java.util.stream.Stream;
@@ -19,6 +26,7 @@
1926
import static net.fabricmc.fabric.api.client.command.v1.ClientCommandManager.literal;
2027

2128
public class Commands {
29+
private static final Gson GSON = new Gson();
2230
public static final @NotNull Set<String> KNOWN_PLAYERS = new HashSet<>();
2331

2432
public static LiteralArgumentBuilder<FabricClientCommandSource> builderGTell() {
@@ -121,7 +129,7 @@ public static LiteralArgumentBuilder<FabricClientCommandSource> builderGuild() {
121129
.then(literal("role")
122130
.then(argument("member", StringArgumentType.word())
123131
.suggests((ctx, builder) -> {
124-
var set = Mod.guildMembers.getOrDefault(Mod.client.getSelectedGuild(), Collections.emptySet());
132+
Set<GuildMember> set = Mod.guildMembers.getOrDefault(Mod.client.getSelectedGuild(), Collections.emptySet());
125133
return CommandSource.suggestMatching(set.stream().map(GuildMember::name), builder);
126134
})
127135
.then(argument("role", StringArgumentType.word())
@@ -195,6 +203,11 @@ public static LiteralArgumentBuilder<FabricClientCommandSource> builderGuild() {
195203
)
196204
)
197205
)
206+
.then(literal("upload_image")
207+
.then(argument("uuid", StringArgumentType.string())
208+
.executes(ctx -> executeUploadImage(ctx.getSource(), StringArgumentType.getString(ctx, "uuid")))
209+
)
210+
)
198211
;
199212
}
200213

@@ -291,6 +304,31 @@ private static int executeChat(FabricClientCommandSource source, String guildNam
291304
return 1;
292305
}
293306

307+
private static int executeUploadImage(FabricClientCommandSource source, String uuid) {
308+
File image = Mod.images.get(UUID.fromString(uuid));
309+
if (image == null) {
310+
return 0;
311+
}
312+
source.sendFeedback(new TranslatableText("generic.uploading").formatted(Formatting.GRAY));
313+
Thread thread = new Thread(() -> {
314+
try {
315+
byte[] data = Files.readAllBytes(image.toPath());
316+
JsonObject obj = GSON.fromJson(Mod.uploadImage(data), JsonObject.class);
317+
if (!obj.has("uuid")) {
318+
MinecraftClient.getInstance().execute(() -> source.sendError(new TranslatableText("generic.upload_image_failed", new LiteralText(obj.toString()).formatted(Formatting.RED))));
319+
return;
320+
}
321+
String imageUuid = obj.get("uuid").getAsString();
322+
Mod.client.sendMessageToGuild(null, "https://" + ModConfig.getEffectiveApiHost() + "/interchat/image?key=" + imageUuid);
323+
} catch (IOException | URISyntaxException e) {
324+
throw new RuntimeException(e);
325+
}
326+
});
327+
thread.setName("InterChat Upload Image Thread");
328+
thread.start();
329+
return 1;
330+
}
331+
294332
private static String roleTranslationKey(String role) {
295333
return "generic.guild_role." + role.toLowerCase(Locale.ROOT);
296334
}

fabric-1.17/src/main/java/net/azisaba/interchatmod/fabric/Mod.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,11 @@
1919

2020
import javax.net.ssl.SSLContext;
2121
import javax.net.ssl.SSLSocketFactory;
22+
import java.io.File;
2223
import java.io.IOException;
2324
import java.net.HttpURLConnection;
2425
import java.net.URI;
26+
import java.net.URISyntaxException;
2527
import java.net.URL;
2628
import java.nio.charset.StandardCharsets;
2729
import java.util.*;
@@ -32,6 +34,7 @@ public class Mod implements ModInitializer, ModMenuApi {
3234
public static final Timer TIMER = new Timer(true);
3335
public static final Set<Guild> GUILDS = Collections.synchronizedSet(new HashSet<>());
3436
public static final Map<Long, Set<GuildMember>> guildMembers = new ConcurrentHashMap<>();
37+
public static final Map<UUID, File> images = new ConcurrentHashMap<>();
3538
public static WebSocketChatClient client;
3639

3740
@Override
@@ -79,6 +82,17 @@ public void run() {
7982
return ByteStreams.readString(connection.getInputStream(), StandardCharsets.UTF_8);
8083
}
8184

85+
public static String uploadImage(byte[] data) throws IOException, URISyntaxException {
86+
String url = "https://" + ModConfig.getEffectiveApiHost() + "/interchat/upload_image";
87+
HttpURLConnection connection = (HttpURLConnection) new URI(url).toURL().openConnection();
88+
connection.addRequestProperty("Authorization", "Bearer " + ModConfig.apiKey);
89+
connection.setDoOutput(true);
90+
connection.setRequestMethod("POST");
91+
connection.setRequestProperty("Content-Type", "image/png");
92+
connection.getOutputStream().write(data);
93+
return new String(connection.getInputStream().readAllBytes(), StandardCharsets.UTF_8);
94+
}
95+
8296
public static void reconnect() {
8397
try {
8498
if (client != null) {
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package net.azisaba.interchatmod.fabric.mixin;
2+
3+
import net.azisaba.interchatmod.fabric.Mod;
4+
import net.minecraft.client.MinecraftClient;
5+
import net.minecraft.client.texture.NativeImage;
6+
import net.minecraft.client.util.ScreenshotRecorder;
7+
import net.minecraft.text.*;
8+
import net.minecraft.util.Formatting;
9+
import org.spongepowered.asm.mixin.Mixin;
10+
import org.spongepowered.asm.mixin.injection.At;
11+
import org.spongepowered.asm.mixin.injection.Inject;
12+
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
13+
14+
import java.io.File;
15+
import java.util.UUID;
16+
import java.util.function.Consumer;
17+
18+
@Mixin(ScreenshotRecorder.class)
19+
public class MixinScreenshotRecorder {
20+
@Inject(at = @At(value = "INVOKE", target = "Ljava/util/function/Consumer;accept(Ljava/lang/Object;)V"), method = "method_1661")
21+
private static void onSaveScreenshot(NativeImage nativeImage, File file, Consumer<Text> consumer, CallbackInfo ci) {
22+
UUID uuid = UUID.randomUUID();
23+
MutableText text = new LiteralText("");
24+
text.append("[↑");
25+
text.append(new TranslatableText("generic.upload"));
26+
text.append("↑]");
27+
text.styled(style -> style
28+
.withColor(Formatting.AQUA)
29+
.withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new TranslatableText("generic.upload.tooltip")))
30+
.withClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/cguild upload_image " + uuid)));
31+
MinecraftClient.getInstance().execute(() -> consumer.accept(text));
32+
Mod.images.put(uuid, file);
33+
}
34+
}

fabric-1.17/src/main/resources/fabric.mod.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
"interchatmod.mixins.json"
2525
],
2626
"depends": {
27-
"fabricloader": ">=0.14",
27+
"fabricloader": ">=0.13",
2828
"fabric": ">=0.46",
2929
"minecraft": ">=1.17",
3030
"java": ">=16"
Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
{
2-
"required": true,
3-
"package": "net.azisaba.interchatmod.fabric.mixin",
4-
"compatibilityLevel": "JAVA_16",
5-
"mixins": [
6-
"MixinClientPlayerEntity",
7-
"MixinMinecraftClient"
8-
],
9-
"injectors": {
10-
"defaultRequire": 1
11-
}
2+
"required": true,
3+
"package": "net.azisaba.interchatmod.fabric.mixin",
4+
"compatibilityLevel": "JAVA_16",
5+
"mixins": [
6+
"MixinClientPlayerEntity",
7+
"MixinMinecraftClient",
8+
"MixinScreenshotRecorder"
9+
],
10+
"injectors": {
11+
"defaultRequire": 1
12+
}
1213
}

0 commit comments

Comments
 (0)