diff --git a/data/GameAnnouncement.json b/data/GameAnnouncement.json index 96c88f17c..57cd72c8e 100644 --- a/data/GameAnnouncement.json +++ b/data/GameAnnouncement.json @@ -1,19 +1,19 @@ { + "t": "{{SYSTEM_TIME}}", "list": [ { "ann_id": 1, "title": "Welcome to Grasscutter!", "subtitle": "Welcome!", - "banner": "https://uploadstatic-sea.mihoyo.com/announcement/2020/09/17/f4aa42d505822805eebf4a55d72a78d8_2755691727027973637.jpg", + "banner": "{{DISPATCH_PUBLIC}}/hk4e/announcement/assets/banner/1.jpg", "content": "

Hi there!

First of all, welcome to Grasscutter. If you have any issues, please let us know so that Lawnmower can help you!


〓Discord〓

https://discord.gg/T5vZU6UyeG

〓GitHub〓https://github.com/Grasscutters/Grasscutter", - "lang": "en-US" }, { "ann_id": 2, "title": "How to use announcements", "subtitle": "How to use announcements", - "banner": "https://uploadstatic-sea.mihoyo.com/announcement/2020/09/17/f4aa42d505822805eebf4a55d72a78d8_2755691727027973637.jpg", + "banner": "{{DISPATCH_PUBLIC}}/hk4e/announcement/assets/banner/2.jpg", "content": "

Announcement content uses HTML. The specific content of the announcement is stored in the program directory GameAnnouncement.json, while GameAnnouncementList.json stores the announcement list data.

GameAnnouncement

ParameterDescription
ann_idUnique ID
titleTitle shown at the top of the content
subtitleShort title shown on the left
bannerImage to display between content and title
contentContent body in HTML
langLanguage code for this entry

GameAnnouncementList

If you want to add an announcement, please add the list data in the announcement type corresponding to GameAnnouncementList, and finally add the announcement content in GameAnnouncement.

", "lang": "en-US" } diff --git a/data/GameAnnouncementList.json b/data/GameAnnouncementList.json index 7464b3b0f..3697703a3 100644 --- a/data/GameAnnouncementList.json +++ b/data/GameAnnouncementList.json @@ -1,15 +1,14 @@ { - "t": "System.currentTimeMillis()", + "t": "{{SYSTEM_TIME}}", "list": [ { "list": [ { "ann_id": 1, - "title": "Welcome to Grasscutter!", "subtitle": "Welcome!", - "banner": "https://uploadstatic-sea.mihoyo.com/announcement/2020/09/22/7d85f19b152d218e73224d7c138a0fd0_5818585260283672899.jpg", - "tag_icon": "https://uploadstatic-sea.mihoyo.com/announcement/2020/03/05/a2588f1a51faee9fa8dfe9aead649dd6_7237021399135895303.png", + "banner": "{{DISPATCH_PUBLIC}}/hk4e/announcement/assets/banner/1.jpg", + "tag_icon": "{{DISPATCH_PUBLIC}}/hk4e/announcement/assets/tag_icon.png", "type": 2, "type_label": "System", "lang": "en-US", @@ -22,8 +21,8 @@ "ann_id": 2, "title": "How to use announcements", "subtitle": "How to use announcements", - "banner": "https://uploadstatic-sea.mihoyo.com/announcement/2020/09/22/7d85f19b152d218e73224d7c138a0fd0_5818585260283672899.jpg", - "tag_icon": "https://uploadstatic-sea.mihoyo.com/announcement/2020/03/05/a2588f1a51faee9fa8dfe9aead649dd6_7237021399135895303.png", + "banner": "{{DISPATCH_PUBLIC}}/hk4e/announcement/assets/banner/2.jpg", + "tag_icon": "{{DISPATCH_PUBLIC}}/hk4e/announcement/assets/tag_icon.png", "type": 2, "type_label": "System", "lang": "en-US", @@ -59,11 +58,5 @@ ], "timezone": -5, "alert": false, - "alert_id": 0, - "pic_list": [], - "pic_total": 0, - "pic_type_list": [], - "pic_alert": false, - "pic_alert_id": 0, - "static_sign": "" + "alert_id": 0 } \ No newline at end of file diff --git a/src/main/java/emu/grasscutter/server/http/handlers/AnnouncementsHandler.java b/src/main/java/emu/grasscutter/server/http/handlers/AnnouncementsHandler.java index 1b87225e9..c4776a4b4 100644 --- a/src/main/java/emu/grasscutter/server/http/handlers/AnnouncementsHandler.java +++ b/src/main/java/emu/grasscutter/server/http/handlers/AnnouncementsHandler.java @@ -6,6 +6,7 @@ import emu.grasscutter.server.http.Router; import emu.grasscutter.utils.FileUtils; import emu.grasscutter.utils.Utils; import express.Express; +import express.http.MediaType; import express.http.Request; import express.http.Response; import io.javalin.Javalin; @@ -13,27 +14,15 @@ import io.javalin.Javalin; import java.io.File; import java.io.FileInputStream; import java.io.IOException; -import java.nio.file.Paths; +import java.nio.charset.StandardCharsets; import java.util.Objects; -import static emu.grasscutter.Configuration.DATA; +import static emu.grasscutter.Configuration.*; /** * Handles requests related to the announcements page. */ public final class AnnouncementsHandler implements Router { - private static String template, swjs, vue; - - public AnnouncementsHandler() { - var templateFile = new File(Utils.toFilePath(DATA("/hk4e/announcement/index.html"))); - var swjsFile = new File(Utils.toFilePath(DATA("/hk4e/announcement/sw.js"))); - var vueFile = new File(Utils.toFilePath(DATA("/hk4e/announcement/vue.min.js"))); - - template = templateFile.exists() ? new String(FileUtils.read(template)) : null; - swjs = swjsFile.exists() ? new String(FileUtils.read(swjs)) : null; - vue = vueFile.exists() ? new String(FileUtils.read(vueFile)) : null; - } - @Override public void applyRoutes(Express express, Javalin handle) { // hk4e-api-os.hoyoverse.com express.all("/common/hk4e_global/announcement/api/getAlertPic", new HttpJsonResponse("{\"retcode\":0,\"message\":\"OK\",\"data\":{\"total\":0,\"list\":[]}}")); @@ -47,58 +36,57 @@ public final class AnnouncementsHandler implements Router { express.all("/hk4e_global/mdk/shopwindow/shopwindow/listPriceTier", new HttpJsonResponse("{\"retcode\":0,\"message\":\"OK\",\"data\":{\"suggest_currency\":\"USD\",\"tiers\":[]}}")); express.get("/hk4e/announcement/*", AnnouncementsHandler::getPageResources); - express.get("/sw.js", AnnouncementsHandler::getPageResources); - express.get("/dora/lib/vue/2.6.11/vue.min.js", AnnouncementsHandler::getPageResources); } private static void getAnnouncement(Request request, Response response) { + String data = ""; if (Objects.equals(request.baseUrl(), "/common/hk4e_global/announcement/api/getAnnContent")) { - String data = readToString(Paths.get(DATA("GameAnnouncement.json")).toFile()); - response.send("{\"retcode\":0,\"message\":\"OK\",\"data\":" + data + "}"); + data = readToString(new File(Utils.toFilePath(DATA("GameAnnouncement.json")))); } else if (Objects.equals(request.baseUrl(), "/common/hk4e_global/announcement/api/getAnnList")) { - String data = readToString(Paths.get(DATA("GameAnnouncementList.json")).toFile()) - .replace("System.currentTimeMillis()", String.valueOf(System.currentTimeMillis())); - response.send("{\"retcode\":0,\"message\":\"OK\",\"data\": " + data + "}"); + data = readToString(new File(Utils.toFilePath(DATA("GameAnnouncementList.json")))); + } else { + response.send("{\"retcode\":404,\"message\":\"Unknown request path\"}"); } + + if (data.isEmpty()) { + response.send("{\"retcode\":500,\"message\":\"Unable to fetch requsted content\"}"); + return; + } + + String dispatchDomain = "http" + (HTTP_ENCRYPTION.useInRouting ? "s" : "") + "://" + + lr(HTTP_INFO.accessAddress, HTTP_INFO.bindAddress) + ":" + + lr(HTTP_INFO.accessPort, HTTP_INFO.bindPort); + + data = data + .replace("{{DISPATCH_PUBLIC}}", dispatchDomain) + .replace("{{SYSTEM_TIME}}", String.valueOf(System.currentTimeMillis())); + response.send("{\"retcode\":0,\"message\":\"OK\",\"data\": " + data + "}"); } private static void getPageResources(Request request, Response response) { - var path = request.path(); - switch(path) { - case "/sw.js" -> response.send(swjs); - case "/hk4e/announcement/index.html" -> response.send(template); - case "/dora/lib/vue/2.6.11/vue.min.js" -> response.send(vue); - - default -> { - File renderFile = new File(Utils.toFilePath(DATA(path))); - if(!renderFile.exists()) { - Grasscutter.getLogger().info("File not exist: " + path); - return; - } - - String ext = path.substring(path.lastIndexOf(".") + 1); - if ("css".equals(ext)) { - response.type("text/css"); - response.send(FileUtils.read(renderFile)); - } else { - response.send(FileUtils.read(renderFile)); - } - } + String filename = Utils.toFilePath(DATA(request.path())); + File file = new File(filename); + if (file.exists() && file.isFile()) { + MediaType fromExtension = MediaType.getByExtension(filename.substring(filename.lastIndexOf(".") + 1)); + response.type((fromExtension != null) ? fromExtension.getMIME() : "application/octet-stream"); + response.send(FileUtils.read(file)); + } else { + Grasscutter.getLogger().warn("File does not exist: " + file); + response.status(404); } } @SuppressWarnings("ResultOfMethodCallIgnored") private static String readToString(File file) { - long length = file.length(); - byte[] content = new byte[(int) length]; + byte[] content = new byte[(int) file.length()]; try { FileInputStream in = new FileInputStream(file); in.read(content); in.close(); } catch (IOException ignored) { - Grasscutter.getLogger().warn("File not found: " + file.getAbsolutePath()); + Grasscutter.getLogger().warn("File does not exist: " + file); } - return new String(content); + return new String(content, StandardCharsets.UTF_8); } }