Skip to content

Commit

Permalink
Use ImgChr to host images
Browse files Browse the repository at this point in the history
  • Loading branch information
zbx1425 committed Jul 26, 2023
1 parent 6dbc759 commit e812fec
Show file tree
Hide file tree
Showing 16 changed files with 233 additions and 68 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.UUID;

public class CommentEntry {
Expand All @@ -29,8 +30,9 @@ public class CommentEntry {
public String initiatorName;
public int messageType;
public String message;
public boolean deleted;
public ThumbImage image;
public boolean deleted;
public int like;

public long fileOffset;

Expand All @@ -51,7 +53,16 @@ public CommentEntry(Player initiator, boolean isAnonymous, int messageType, Stri
}

public CommentEntry(ResourceLocation level, FriendlyByteBuf src, boolean fromFile) {
if (fromFile) fileOffset = src.readerIndex();
if (fromFile) {
fileOffset = src.readerIndex();
src.skipBytes(16);
}

deleted = src.readBoolean();
src.skipBytes(3);
like = src.readInt();
src.skipBytes(4);

id = src.readLong();
timestamp = src.readLong();
this.level = level;
Expand All @@ -61,8 +72,8 @@ public CommentEntry(ResourceLocation level, FriendlyByteBuf src, boolean fromFil
initiatorName = src.readUtf();
messageType = src.readInt();
message = src.readUtf();
deleted = src.readBoolean();
image = new ThumbImage(src.readUtf(), src.readUtf());

if (fromFile) src.skipBytes(16 - (src.readerIndex() % 16));
}

Expand All @@ -72,16 +83,25 @@ public void setLocation(BlockPos location) {
}

public void writeBuffer(FriendlyByteBuf dst, boolean toFile) {
if (toFile) {
dst.writeBytes("=====(C)=Zbx1425".getBytes(StandardCharsets.UTF_8));
}

dst.writeBoolean(deleted);
dst.writeZero(3);
dst.writeInt(like);
dst.writeZero(4);

dst.writeLong(id);
dst.writeLong(timestamp);
dst.writeBlockPos(location);
dst.writeUUID(initiator);
dst.writeUtf(initiatorName);
dst.writeInt(messageType);
dst.writeUtf(message);
dst.writeBoolean(deleted);
dst.writeUtf(image.url);
dst.writeUtf(image.thumbUrl);

if (toFile) dst.writeZero(16 - (dst.writerIndex() % 16));
}

Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
package cn.zbx1425.worldcomment.data.network;

import com.google.gson.JsonObject;
import com.google.gson.JsonParser;

import java.io.IOException;
import java.net.URI;
import java.net.URLEncoder;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class ImageUpload {

private static final HttpClient HTTP_CLIENT = HttpClient.newHttpClient();

private static String apiUrlBase = "https://imgse.com";
private static String loginSubject = "[email protected]";
private static String loginCredential = "Sg5KRGj6h9n5HKKC";

private static String sessionCookie;

public static ThumbImage uploadImage(Path imagePath) throws IOException, InterruptedException {
HttpRequest reqGetToken = HttpRequest.newBuilder(URI.create(apiUrlBase + "/login"))
.header("Cookie", sessionCookie == null ? "" : sessionCookie)
.GET()
.build();
HttpResponse<String> respGetToken = HTTP_CLIENT.send(reqGetToken, HttpResponse.BodyHandlers.ofString());
if (respGetToken.statusCode() >= 400)
throw new IOException("Auth Token HTTP " + respGetToken.statusCode() + "\n" + respGetToken.body());
Pattern tokenPattern = Pattern.compile("auth_token = \"([a-z0-9]*)\"");
Matcher tokenMatcher = tokenPattern.matcher(respGetToken.body());
if (!tokenMatcher.find()) throw new IOException("Cannot locate Auth Token");
String authToken = tokenMatcher.group(1);
respGetToken.headers().firstValue("Set-Cookie").ifPresent(setCookie -> {
sessionCookie = setCookie.split(";")[0];
});
if (sessionCookie == null) throw new IOException("Cannot obtain session cookie");

HttpRequest reqLogin = HttpRequest.newBuilder(URI.create(apiUrlBase + "/login"))
.header("Content-Type", "application/x-www-form-urlencoded")
.header("Cookie", sessionCookie)
.POST(HttpRequest.BodyPublishers.ofString(encodeForm(Map.of(
"login-subject", loginSubject,
"password", loginCredential,
"auth_token", authToken
))))
.build();
HttpResponse<String> respLogin = HTTP_CLIENT.send(reqLogin, HttpResponse.BodyHandlers.ofString());
if (respLogin.statusCode() >= 400)
throw new IOException("Login HTTP " + respGetToken.statusCode() + "\n" + respLogin.body());

MimeMultipartData body = MimeMultipartData.newBuilder()
.withCharset(StandardCharsets.UTF_8)
.addFile("source", imagePath, "application/octet-stream")
.addText("type", "file")
.addText("action", "upload")
.addText("timestamp", Long.toString(System.currentTimeMillis()))
.addText("auth_token", authToken)
.addText("nsfw", "0")
.build();
HttpRequest reqUpload = HttpRequest.newBuilder(URI.create(apiUrlBase + "/json"))
.header("Content-Type", body.getContentType())
.header("Cookie", sessionCookie)
.POST(body.getBodyPublisher())
.build();
HttpResponse<String> respUpload = HTTP_CLIENT.send(reqUpload, HttpResponse.BodyHandlers.ofString());
if (respUpload.statusCode() >= 400)
throw new IOException("Upload HTTP " + respUpload.statusCode() + "\n" + respUpload.body());
JsonObject respObj = JsonParser.parseString(respUpload.body()).getAsJsonObject();
if (!respObj.has("success")) throw new IOException("Upload Fail " + respUpload.body());
return new ThumbImage(
respObj.get("image").getAsJsonObject().get("image").getAsJsonObject().get("url").getAsString(),
respObj.get("image").getAsJsonObject().get("thumb").getAsJsonObject().get("url").getAsString()
);
}

private static String encodeForm(Map<String, String> params) {
StringBuilder result = new StringBuilder();
boolean first = true;
for(Map.Entry<String, String> entry : params.entrySet()){
if (first)
first = false;
else
result.append("&");
result.append(URLEncoder.encode(entry.getKey(), StandardCharsets.UTF_8));
result.append("=");
result.append(URLEncoder.encode(entry.getValue(), StandardCharsets.UTF_8));
}
return result.toString();
}
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,13 @@
package cn.zbx1425.worldcomment.data.network;

import cn.zbx1425.worldcomment.Main;
import cn.zbx1425.worldcomment.data.CommentEntry;
import cn.zbx1425.worldcomment.data.Database;
import cn.zbx1425.worldcomment.network.PacketSubmitCommentC2S;
import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
import net.minecraft.Util;
import net.minecraft.client.Minecraft;
import net.minecraft.client.Screenshot;
import net.minecraft.core.BlockPos;

import java.io.File;
import java.nio.file.Path;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
Expand All @@ -21,18 +18,20 @@ public class SubmitDispatcher {
private static final Executor NETWORK_EXECUTOR = Executors.newSingleThreadExecutor();
private static final Long2ObjectMap<SubmitJob> pendingJobs = new Long2ObjectOpenHashMap<>();

public static long addJob(CommentEntry comment, Path imagePath, Consumer<Exception> callback) {
public static long addJob(CommentEntry comment, Path imagePath, Consumer<SubmitJob> callback) {
synchronized (pendingJobs) {
long jobId = Database.SNOWFLAKE.nextId();
SubmitJob job = new SubmitJob(comment, imagePath, callback);
pendingJobs.put(jobId, job);
if (imagePath != null) {
NETWORK_EXECUTOR.execute(() -> {
try {
job.setImage(ImageHost.uploadImage(imagePath));
job.setImage(ImageUpload.uploadImage(imagePath));
trySendPackage(jobId);
} catch (Exception ex) {
if (job.callback != null) job.callback.accept(ex);
job.exception = ex;
if (job.callback != null) job.callback.accept(job);
Main.LOGGER.error("Upload Image", ex);
removeJob(jobId);
}
});
Expand Down Expand Up @@ -61,6 +60,10 @@ private static void trySendPackage(long jobId) {
PacketSubmitCommentC2S.ClientLogics.send(job.comment);
if (job.callback != null) job.callback.accept(null);
removeJob(jobId);
} else {
if (job.imagePath != null && !job.imageReady) {
if (job.callback != null) job.callback.accept(job);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,10 @@ public class SubmitJob {
public final CommentEntry comment;
public final Path imagePath;
public boolean imageReady, blockPosReady;
public Consumer<Exception> callback;
public Exception exception;
public Consumer<SubmitJob> callback;

public SubmitJob(CommentEntry comment, Path imagePath, Consumer<Exception> callback) {
public SubmitJob(CommentEntry comment, Path imagePath, Consumer<SubmitJob> callback) {
this.comment = comment;
this.imagePath = imagePath;
if (imagePath == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -163,13 +163,18 @@ private void sendReport() {
);
long jobId = SubmitDispatcher.addJob(
comment, checkBoxNoImage.selected() ? null : imagePath,
exception -> Minecraft.getInstance().execute(() -> {
if (exception == null) {
data -> Minecraft.getInstance().execute(() -> {
if (data == null) {
Minecraft.getInstance().player.displayClientMessage(
Component.translatable("gui.worldcomment.send_finish"), false);
} else {
Minecraft.getInstance().player.displayClientMessage(
Component.translatable("gui.worldcomment.send_fail", exception.getMessage()), true);
if (data.exception != null) {
Minecraft.getInstance().player.displayClientMessage(
Component.translatable("gui.worldcomment.send_fail", data.exception.getMessage()), false);
} else {
Minecraft.getInstance().player.displayClientMessage(
Component.translatable("gui.worldcomment.send_upload_incomplete"), false);
}
}
}
));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ private void calculateHeight() {
int textHeight = 26
+ (comment.message.isEmpty() ? 0 : font.wordWrapHeight(comment.message, picWidth * 2 - 8))
+ 4;
int picHeight = 20 + (comment.image.url.isEmpty() ? 0 : (picWidth * 9 / 16)) + 4;
int picHeight = 20 + (comment.image.url.isEmpty() ? 0 : (picWidth)) + 4;
height = Math.max(Math.max(textHeight, picHeight), 28 + 4);
}

Expand All @@ -67,7 +67,7 @@ guiGraphics, getX(), getY(), getWidth(), getHeight(),

if (!comment.image.url.isEmpty()) {
int picWidth = (width - 16) / 3;
int picHeight = picWidth * 9 / 16;
int picHeight = picWidth;
String imageUrl = comment.image.thumbUrl.isEmpty() ? comment.image.url : comment.image.thumbUrl;
RenderSystem.setShaderTexture(0, ImageDownload.getTexture(imageUrl).getId());
RenderSystem.setShader(GameRenderer::getPositionTexShader);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,6 @@ public class InGameHudMixin {

@Inject(method = "render", at = @At(value = "TAIL"))
public void render(GuiGraphics guiGraphics, float partialTick, CallbackInfo callbackInfo) {
if (!minecraft.options.hideGui && minecraft.screen == null
&& minecraft.options.getCameraType().isFirstPerson()) {
CommentOverlayRenderer.render(guiGraphics, partialTick);
ControlTipRenderer.render(guiGraphics);
}

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package cn.zbx1425.worldcomment.network;

public class PacketCommentDataUIS2C {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package cn.zbx1425.worldcomment.network;

import cn.zbx1425.worldcomment.ClientPlatform;
import cn.zbx1425.worldcomment.Main;
import cn.zbx1425.worldcomment.data.CommentEntry;
import io.netty.buffer.Unpooled;
import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.level.ChunkPos;

import java.util.List;
import java.util.Map;

public class PacketRequestCommentUIC2S {

public static final ResourceLocation IDENTIFIER = new ResourceLocation(Main.MOD_ID, "request_region");

public static class ClientLogics {

public static void send(ResourceLocation level, List<ChunkPos> requests) {
FriendlyByteBuf buffer = new FriendlyByteBuf(Unpooled.buffer());
buffer.writeResourceLocation(level);
buffer.writeInt(requests.size());
for (ChunkPos request : requests) {
buffer.writeChunkPos(request);
}
ClientPlatform.sendPacketToServer(IDENTIFIER, buffer);
}
}

public static void handle(MinecraftServer server, ServerPlayer initiator, FriendlyByteBuf buffer) {
ResourceLocation level = buffer.readResourceLocation();
Map<ChunkPos, List<CommentEntry>> results = new Object2ObjectArrayMap<>();
int size = buffer.readInt();
for (int i = 0; i < size; i++) {
ChunkPos request = buffer.readChunkPos();
List<CommentEntry> regionResults = Main.DATABASE.comments.queryRegion(level, request);
results.put(request, regionResults);
}
PacketRegionDataS2C.send(initiator, level, results);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ private static WidgetCommentEntry getWidget(CommentEntry entry) {
return widgets.computeIfAbsent(entry, WidgetCommentEntry::new);
}

public static void render(GuiGraphics guiGraphics, float partialTick) {
public static void render(GuiGraphics guiGraphics) {
int pickedCommentsSize = ClientRayPicking.pickedComments.size();
if (pickedCommentsSize > 0) {
int[] yOffsets = new int[pickedCommentsSize];
Expand All @@ -44,7 +44,7 @@ public static void render(GuiGraphics guiGraphics, float partialTick) {
guiGraphics.guiWidth() / 2 - 30
);
if (widget.getY() + widget.getHeight() > 0 && widget.getY() < guiGraphics.guiHeight()) {
widget.render(guiGraphics, 0, 0, partialTick);
widget.render(guiGraphics, 0, 0, 0);
}
}
if (pickedCommentsSize > 1) {
Expand Down
Loading

0 comments on commit e812fec

Please sign in to comment.