diff --git a/README.md b/README.md index c721429..1724313 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# GuizhanLib 插件 +# GuizhanLibPlugin 鬼斩前置库插件 将 GuizhanLib 库整合到插件中,并提供自动更新站点选择功能。 @@ -6,17 +6,17 @@ 从构建站下载: [点击前往](https://builds.guizhanss.com/ybw0014/GuizhanLibPlugin/master) -![构建状态](https://builds.guizhanss.com/ybw0014/GuizhanLibPlugin/master/badge.svg) +![构建状态](https://builds.guizhanss.com/api/badge/ybw0014/GuizhanLibPlugin/master/latest) ## 如何使用 ### 对于服主 -将下载好的jar放入`plugins`目录,然后重启服务器即可。 +将下载好的 jar 放入`plugins`目录,然后重启服务器即可。 ### 对于开发者 -将GuizhanLibPlugin添加为依赖项: +将 GuizhanLibPlugin 添加为依赖项: [![Maven Central](https://img.shields.io/maven-central/v/net.guizhanss/GuizhanLibPlugin.svg?label=Maven%20Central)](https://search.maven.org/search?q=g:%22net.guizhanss%22%20AND%20a:%22GuizhanLibPlugin%22) @@ -29,21 +29,21 @@ ``` -并在`plugin.yml`中添加`GuizhanLibPlugin`为前置: +并在 `plugin.yml` 中添加 `GuizhanLibPlugin` 为前置: ```yaml depend: - GuizhanLibPlugin ``` -你也可以添加`GuizhanLibPlugin`为软前置: +你也可以添加 `GuizhanLibPlugin` 为软前置: ```yaml softdepend: - GuizhanLibPlugin ``` -并在插件的`onEnable`方法添加以下代码片段(尽量添加在前面): +并在插件的 `onEnable` 方法添加以下代码片段(尽量添加在前面): ```java if (!getServer().getPluginManager().isPluginEnabled("GuizhanLibPlugin")) { diff --git a/src/main/java/net/guizhanss/guizhanlibplugin/GuizhanLibPlugin.java b/src/main/java/net/guizhanss/guizhanlibplugin/GuizhanLibPlugin.java index c997fc2..516b593 100644 --- a/src/main/java/net/guizhanss/guizhanlibplugin/GuizhanLibPlugin.java +++ b/src/main/java/net/guizhanss/guizhanlibplugin/GuizhanLibPlugin.java @@ -5,7 +5,7 @@ import net.guizhanss.guizhanlibplugin.config.ConfigManager; import net.guizhanss.guizhanlibplugin.setup.MinecraftLanguageSetup; import net.guizhanss.guizhanlibplugin.updater.GuizhanUpdater; -import net.guizhanss.guizhanlibplugin.updater.UniversalUpdater; +import net.guizhanss.guizhanlibplugin.updater.universal.v2.UniversalUpdater; import org.bstats.bukkit.Metrics; import org.bstats.charts.DrilldownPie; import org.bstats.charts.SimplePie; @@ -58,6 +58,7 @@ public void enable() { @Override public void disable() { + // nothing to do } private void setupMinecraftLanguage() { diff --git a/src/main/java/net/guizhanss/guizhanlibplugin/config/ConfigManager.java b/src/main/java/net/guizhanss/guizhanlibplugin/config/ConfigManager.java index 0e645fe..290f45c 100644 --- a/src/main/java/net/guizhanss/guizhanlibplugin/config/ConfigManager.java +++ b/src/main/java/net/guizhanss/guizhanlibplugin/config/ConfigManager.java @@ -7,12 +7,8 @@ import javax.annotation.Nonnull; public final class ConfigManager { - private final GuizhanLibPlugin plugin; - @Getter private final AddonConfig config; - @Getter - private final AddonConfig updaterConfig; @Getter private final boolean debugEnabled; @@ -24,10 +20,7 @@ public final class ConfigManager { private final String updaterLang; public ConfigManager(@Nonnull GuizhanLibPlugin plugin) { - this.plugin = plugin; - config = new AddonConfig(plugin, "config.yml"); - updaterConfig = new AddonConfig(plugin, "updater.yml"); debugEnabled = config.getBoolean("debug", false); autoUpdateEnabled = config.getBoolean("auto-update", true); diff --git a/src/main/java/net/guizhanss/guizhanlibplugin/updater/GuizhanBuildsUpdaterWrapper.java b/src/main/java/net/guizhanss/guizhanlibplugin/updater/GuizhanBuildsUpdaterWrapper.java index f03e36f..e5e1f89 100644 --- a/src/main/java/net/guizhanss/guizhanlibplugin/updater/GuizhanBuildsUpdaterWrapper.java +++ b/src/main/java/net/guizhanss/guizhanlibplugin/updater/GuizhanBuildsUpdaterWrapper.java @@ -11,9 +11,9 @@ * The universal updater wrapper. * * @author ybw0014 - * @deprecated This class is deprecated, use {@link GuizhanUpdater} instead. + * @deprecated Use {@link GuizhanUpdater} instead. */ -@Deprecated(since = "1.3.0") +@Deprecated(since = "1.3.0", forRemoval = true) @UtilityClass public final class GuizhanBuildsUpdaterWrapper { /** diff --git a/src/main/java/net/guizhanss/guizhanlibplugin/updater/UniversalUpdaterTask.java b/src/main/java/net/guizhanss/guizhanlibplugin/updater/UniversalUpdaterTask.java deleted file mode 100644 index 8cfc230..0000000 --- a/src/main/java/net/guizhanss/guizhanlibplugin/updater/UniversalUpdaterTask.java +++ /dev/null @@ -1,104 +0,0 @@ -package net.guizhanss.guizhanlibplugin.updater; - -import com.google.gson.Gson; -import com.google.gson.reflect.TypeToken; -import lombok.RequiredArgsConstructor; -import net.guizhanss.guizhanlib.updater.GuizhanBuildsCNUpdater; -import net.guizhanss.guizhanlib.updater.GuizhanBuildsUpdater; -import net.guizhanss.guizhanlibplugin.GuizhanLibPlugin; - -import javax.annotation.Nonnull; -import java.io.BufferedReader; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.nio.charset.StandardCharsets; -import java.util.List; -import java.util.Map; -import java.util.logging.Level; - -@RequiredArgsConstructor -public class UniversalUpdaterTask implements Runnable { - - private static final Gson GSON = new Gson(); - - private final UniversalUpdater updater; - private Map lang; - - @Override - public void run() { - // lang - if (!loadLanguage()) { - return; - } - - // updater main - final List records = updater.getRecords(); - log(Level.INFO, lang.get("loading")); - log(Level.INFO, lang.get("loaded"), records.size()); - - // run tasks - for (int i = 0; i < records.size(); i++) { - final UpdaterRecord record = records.get(i); - log(Level.INFO, lang.get("task.running"), i + 1, record.plugin().getName()); - runTask(record); - } - } - - private boolean loadLanguage() { - final GuizhanLibPlugin plugin = GuizhanLibPlugin.getInstance(); - InputStream stream; - try { - stream = - plugin.getClass().getResourceAsStream("/updater/" + GuizhanLibPlugin.getConfigManager().getUpdaterLang() + ".json"); - } catch (Exception ex) { - log(Level.WARNING, "Failed to load updater language file, using default en_US."); - try { - stream = plugin.getClass().getResourceAsStream("/updater/en_US.json"); - } catch (Exception e) { - log(Level.SEVERE, "Failed to load default updater language file, please report this!"); - return false; - } - } - - try { - BufferedReader reader = new BufferedReader(new InputStreamReader( - stream, StandardCharsets.UTF_8 - )); - // @formatter:off - lang = GSON.fromJson(reader, new TypeToken>() {}.getType()); - // @formatter:on - log(Level.INFO, lang.get("init")); - } catch (Exception ex) { - log(Level.SEVERE, ex, "Failed to load updater language file, please report this!"); - return false; - } - - return true; - } - - private void runTask(@Nonnull UpdaterRecord record) { - // check if the plugin is disabled - if (!record.plugin().isEnabled()) { - log(Level.INFO, lang.get("task.disabled"), record.plugin().getName()); - return; - } - try { - switch (UpdaterLocation.getLocation(GuizhanLibPlugin.getConfigManager().getUpdaterLocation())) { - case CN -> new GuizhanBuildsCNUpdater(record.plugin(), record.file(), record.githubUser(), - record.githubRepo(), record.githubBranch(), record.updaterConfig()).start(); - case GLOBAL -> new GuizhanBuildsUpdater(record.plugin(), record.file(), record.githubUser(), - record.githubRepo(), record.githubBranch(), record.updaterConfig()).start(); - } - } catch (Exception ex) { - log(Level.SEVERE, ex, lang.get("task.failed"), record.plugin().getName()); - } - } - - private void log(Level level, String message, Object... args) { - GuizhanLibPlugin.log(level, message, args); - } - - private void log(Level level, Throwable throwable, String message, Object... args) { - GuizhanLibPlugin.log(level, throwable, message, args); - } -} diff --git a/src/main/java/net/guizhanss/guizhanlibplugin/updater/UniversalUpdater.java b/src/main/java/net/guizhanss/guizhanlibplugin/updater/universal/v2/UniversalUpdater.java similarity index 93% rename from src/main/java/net/guizhanss/guizhanlibplugin/updater/UniversalUpdater.java rename to src/main/java/net/guizhanss/guizhanlibplugin/updater/universal/v2/UniversalUpdater.java index dde445d..749a702 100644 --- a/src/main/java/net/guizhanss/guizhanlibplugin/updater/UniversalUpdater.java +++ b/src/main/java/net/guizhanss/guizhanlibplugin/updater/universal/v2/UniversalUpdater.java @@ -1,4 +1,4 @@ -package net.guizhanss.guizhanlibplugin.updater; +package net.guizhanss.guizhanlibplugin.updater.universal.v2; import lombok.Getter; import net.guizhanss.guizhanlib.updater.UpdaterConfig; diff --git a/src/main/java/net/guizhanss/guizhanlibplugin/updater/universal/v2/UniversalUpdaterTask.java b/src/main/java/net/guizhanss/guizhanlibplugin/updater/universal/v2/UniversalUpdaterTask.java new file mode 100644 index 0000000..bbbf353 --- /dev/null +++ b/src/main/java/net/guizhanss/guizhanlibplugin/updater/universal/v2/UniversalUpdaterTask.java @@ -0,0 +1,195 @@ +package net.guizhanss.guizhanlibplugin.updater.universal.v2; + +import com.google.gson.Gson; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.reflect.TypeToken; +import lombok.RequiredArgsConstructor; +import net.guizhanss.guizhanlib.updater.GuizhanBuildsCNUpdater; +import net.guizhanss.guizhanlib.updater.GuizhanBuildsUpdater; +import net.guizhanss.guizhanlib.updater.LocaleKey; +import net.guizhanss.guizhanlibplugin.GuizhanLibPlugin; +import org.bukkit.plugin.Plugin; +import org.bukkit.plugin.java.JavaPlugin; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.io.BufferedInputStream; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileOutputStream; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.URI; +import java.net.URL; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.nio.charset.StandardCharsets; +import java.text.MessageFormat; +import java.util.List; +import java.util.Map; +import java.util.MissingResourceException; +import java.util.logging.Level; + +@RequiredArgsConstructor +public class UniversalUpdaterTask implements Runnable { + + private static final String BUILD_PATH = "api/build/%s/%s/%s/latest?status=success"; + private static final String DOWNLOAD_PATH = "api/download/%s/%s/%s/%d"; + + private static final HttpClient HTTP_CLIENT = HttpClient.newHttpClient(); + private static final Gson GSON = new Gson(); + private static final UpdaterLocation location = UpdaterLocation.getLocation(GuizhanLibPlugin.getConfigManager().getUpdaterLocation()); + + private final UniversalUpdater updater; + private Map lang; + + @Override + public void run() { + // lang + if (!loadLanguage()) { + return; + } + + // updater main + final List records = updater.getRecords(); + log(Level.INFO, lang.get("loading")); + log(Level.INFO, lang.get("loaded"), records.size()); + + // run tasks + for (int i = 0; i < records.size(); i++) { + final UpdaterRecord r = records.get(i); + log(Level.INFO, "task.running", i + 1, r.plugin().getName()); + runTask(r); + } + } + + private boolean loadLanguage() { + final GuizhanLibPlugin plugin = GuizhanLibPlugin.getInstance(); + InputStream stream; + try { + stream = + plugin.getClass().getResourceAsStream("/updater/" + GuizhanLibPlugin.getConfigManager().getUpdaterLang() + ".json"); + } catch (Exception ex) { + GuizhanLibPlugin.log(Level.WARNING, "Failed to load updater language file, using default en_US."); + try { + stream = plugin.getClass().getResourceAsStream("/updater/en_US.json"); + } catch (Exception e) { + GuizhanLibPlugin.log(Level.SEVERE, "Failed to load default updater language file, please report this!"); + return false; + } + } + + try { + BufferedReader reader = new BufferedReader(new InputStreamReader( + stream, StandardCharsets.UTF_8 + )); + // @formatter:off + lang = GSON.fromJson(reader, new TypeToken>() {}.getType()); + // @formatter:on + log(Level.INFO, "init"); + } catch (Exception ex) { + GuizhanLibPlugin.log(Level.SEVERE, ex, "Failed to load updater language file, please report this!"); + return false; + } + + return true; + } + + private void runTask(@Nonnull UpdaterRecord record) { + // check if the plugin is disabled + if (!record.plugin().isEnabled()) { + log(Level.INFO, "task.disabled", record.plugin().getName()); + return; + } + + try { + var buildResp = fetchJson(URI.create( + location.getBaseUrl() + String.format(BUILD_PATH, record.githubUser(), record.githubRepo(), record.githubBranch()) + )); + if (buildResp == null) { + throw new IllegalArgumentException(lang.get("tasks.no-info")); + } + var buildResponse = buildResp.getAsJsonObject(); + if (buildResponse.get("code").getAsInt() != 0) { + throw new IllegalArgumentException(lang.get("tasks.no-info")); + } + + JsonObject build = buildResponse.get("data").getAsJsonObject(); + + if (isLatest(record.plugin(), build)) { + log(Level.INFO, "task.no-update", record.plugin().getName()); + return; + } + + // check if the requirement is check only + if (record.updaterConfig().checkOnly()) { + log(Level.INFO, "task.has-update", record.plugin().getName()); + log(Level.INFO, "task.check-only"); + return; + } + + // download the latest build + var buildId = build.get("id").getAsInt(); + var buildVersion = build.get("target").getAsString().replace(".jar", "").replace(record.plugin().getName() + "-", ""); + + log(Level.INFO, "task.downloading", record.plugin().getName(), buildVersion); + downloadBuild(record, buildId); + log(Level.INFO, "task.downloaded", record.plugin().getName(), buildVersion); + } catch (Exception ex) { + log(Level.SEVERE, ex, "task.failed", record.plugin().getName()); + } + } + + @Nullable + private JsonElement fetchJson(URI uri) { + try { + HttpRequest request = HttpRequest.newBuilder() + .uri(uri) + .GET() + .build(); + HttpResponse response = HTTP_CLIENT.send(request, HttpResponse.BodyHandlers.ofString()); + return GSON.fromJson(response.body(), JsonElement.class); + } catch (Exception ex) { + log(Level.SEVERE, ex, "task.failed"); + return null; + } + } + + private boolean isLatest(Plugin plugin, JsonObject build) { + var latestBuildVer = build.get("target").getAsString(); + var currentBuildVer = MessageFormat.format("{0}-{1}.jar", plugin.getName(), plugin.getDescription().getVersion()); + return latestBuildVer.equals(currentBuildVer); + } + + private void downloadBuild(UpdaterRecord record, int buildId) throws Exception { + BufferedInputStream input = new BufferedInputStream(URI.create( + location.getBaseUrl() + String.format(DOWNLOAD_PATH, record.githubUser(), record.githubRepo(), record.githubBranch(), buildId) + ).toURL().openStream()); + FileOutputStream output = new FileOutputStream(new File("plugins/" + record.plugin().getServer().getUpdateFolder(), record.file().getName())); + byte[] data = new byte[1024]; + int read; + + while ((read = input.read(data, 0, 1024)) != -1) { + output.write(data, 0, read); + } + + input.close(); + output.close(); + } + + private void log(Level level, String key, Object... args) { + String msg = lang.get(key) != null ? lang.get(key) : key; + GuizhanLibPlugin.log(level, msg, args); + } + + private void log(Level level, Throwable throwable, String key, Object... args) { + String msg = lang.get(key) != null ? lang.get(key) : key; + if (GuizhanLibPlugin.getConfigManager().isDebugEnabled()) { + GuizhanLibPlugin.log(level, throwable, msg, args); + } else { + GuizhanLibPlugin.log(level, msg, args); + } + } +} diff --git a/src/main/java/net/guizhanss/guizhanlibplugin/updater/UpdaterLocation.java b/src/main/java/net/guizhanss/guizhanlibplugin/updater/universal/v2/UpdaterLocation.java similarity index 93% rename from src/main/java/net/guizhanss/guizhanlibplugin/updater/UpdaterLocation.java rename to src/main/java/net/guizhanss/guizhanlibplugin/updater/universal/v2/UpdaterLocation.java index 58c5783..3159ff2 100644 --- a/src/main/java/net/guizhanss/guizhanlibplugin/updater/UpdaterLocation.java +++ b/src/main/java/net/guizhanss/guizhanlibplugin/updater/universal/v2/UpdaterLocation.java @@ -1,4 +1,4 @@ -package net.guizhanss.guizhanlibplugin.updater; +package net.guizhanss.guizhanlibplugin.updater.universal.v2; import lombok.AllArgsConstructor; import lombok.Getter; diff --git a/src/main/java/net/guizhanss/guizhanlibplugin/updater/UpdaterRecord.java b/src/main/java/net/guizhanss/guizhanlibplugin/updater/universal/v2/UpdaterRecord.java similarity index 81% rename from src/main/java/net/guizhanss/guizhanlibplugin/updater/UpdaterRecord.java rename to src/main/java/net/guizhanss/guizhanlibplugin/updater/universal/v2/UpdaterRecord.java index e023c40..93fcd73 100644 --- a/src/main/java/net/guizhanss/guizhanlibplugin/updater/UpdaterRecord.java +++ b/src/main/java/net/guizhanss/guizhanlibplugin/updater/universal/v2/UpdaterRecord.java @@ -1,4 +1,4 @@ -package net.guizhanss.guizhanlibplugin.updater; +package net.guizhanss.guizhanlibplugin.updater.universal.v2; import net.guizhanss.guizhanlib.updater.UpdaterConfig; import org.bukkit.plugin.Plugin; diff --git a/src/main/resources/updater.yml b/src/main/resources/updater.yml deleted file mode 100644 index 9ac18f8..0000000 --- a/src/main/resources/updater.yml +++ /dev/null @@ -1,2 +0,0 @@ -# 自动更新配置 - diff --git a/src/main/resources/updater/en_US.json b/src/main/resources/updater/en_US.json index 3c3e90e..8ba568a 100644 --- a/src/main/resources/updater/en_US.json +++ b/src/main/resources/updater/en_US.json @@ -4,5 +4,11 @@ "loaded": "Found {0} updater tasks.", "task.running": "Running task {0} ({1})...", "task.disabled": "Task {0} plugin ({1}) is disabled...", - "task.failed": "Updater task ({0}) failed!" + "task.failed": "Auto updater task ({0}) failed!", + "task.no-info": "Cannot fetch build info for {0}!", + "task.has-update": "There is an update available for {0}!", + "task.no-update": "{0} is up to date!", + "task.check-only": "The updater is set to check updates only, you will need to download the update manually.", + "task.downloading": "Downloading update for {0} ({1})...", + "task.downloaded": "Update downloaded for {0} ({1})! Restart server to apply changes." } diff --git a/src/main/resources/updater/zh_CN.json b/src/main/resources/updater/zh_CN.json index acd5c1d..d958942 100644 --- a/src/main/resources/updater/zh_CN.json +++ b/src/main/resources/updater/zh_CN.json @@ -4,5 +4,11 @@ "loaded": "已找到 {0} 个更新任务。", "task.running": "正在执行任务 {0}({1})...", "task.disabled": "任务 {0} 插件 ({1}) 已禁用...", - "task.failed": "更新任务({0})失败!" + "task.failed": "自动更新任务 ({0}) 失败!", + "task.no-info": "无法获取 {0} 的构建信息!", + "task.has-update": "{0} 有可用的新版本!", + "task.no-update": "{0} 已是最新版本!", + "task.check-only": "自动更新已设置为仅检测更新,你需要手动下载更新。", + "task.downloading": "正在下载更新 {0} ({1})...", + "task.downloaded": "已完成 {0} ({1}) 下载!重启服务器以应用更改。" }