feat: 自动检测 Jenkins 更新
This commit is contained in:
@@ -9,21 +9,30 @@ import cn.hamster3.mc.plugin.core.bukkit.hook.PointAPI;
|
|||||||
import cn.hamster3.mc.plugin.core.bukkit.hook.VaultAPI;
|
import cn.hamster3.mc.plugin.core.bukkit.hook.VaultAPI;
|
||||||
import cn.hamster3.mc.plugin.core.bukkit.listener.CallbackListener;
|
import cn.hamster3.mc.plugin.core.bukkit.listener.CallbackListener;
|
||||||
import cn.hamster3.mc.plugin.core.bukkit.listener.DebugListener;
|
import cn.hamster3.mc.plugin.core.bukkit.listener.DebugListener;
|
||||||
|
import cn.hamster3.mc.plugin.core.bukkit.listener.JenkinsUpdateListener;
|
||||||
import cn.hamster3.mc.plugin.core.bukkit.page.handler.PageHandler;
|
import cn.hamster3.mc.plugin.core.bukkit.page.handler.PageHandler;
|
||||||
import cn.hamster3.mc.plugin.core.bukkit.page.listener.PageListener;
|
import cn.hamster3.mc.plugin.core.bukkit.page.listener.PageListener;
|
||||||
import cn.hamster3.mc.plugin.core.bukkit.util.MinecraftVersion;
|
import cn.hamster3.mc.plugin.core.bukkit.util.MinecraftVersion;
|
||||||
import cn.hamster3.mc.plugin.core.common.api.CoreAPI;
|
import cn.hamster3.mc.plugin.core.common.api.CoreAPI;
|
||||||
|
import cn.hamster3.mc.plugin.core.common.config.YamlConfig;
|
||||||
|
import cn.hamster3.mc.plugin.core.common.util.JenkinsUtils;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import net.kyori.adventure.platform.bukkit.BukkitAudiences;
|
import net.kyori.adventure.platform.bukkit.BukkitAudiences;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.inventory.Inventory;
|
import org.bukkit.inventory.Inventory;
|
||||||
import org.bukkit.inventory.InventoryView;
|
import org.bukkit.inventory.InventoryView;
|
||||||
|
import org.bukkit.plugin.Plugin;
|
||||||
import org.bukkit.plugin.java.JavaPlugin;
|
import org.bukkit.plugin.java.JavaPlugin;
|
||||||
import org.bukkit.scheduler.BukkitTask;
|
import org.bukkit.scheduler.BukkitTask;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.StandardCopyOption;
|
import java.nio.file.StandardCopyOption;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
@@ -58,6 +67,38 @@ public class HamsterCorePlugin extends JavaPlugin {
|
|||||||
return Bukkit.getScheduler().runTaskAsynchronously(instance, runnable);
|
return Bukkit.getScheduler().runTaskAsynchronously(instance, runnable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void showUpdate(@NotNull CommandSender sender) {
|
||||||
|
HamsterCorePlugin.async(() -> {
|
||||||
|
for (Plugin plugin : Bukkit.getPluginManager().getPlugins()) {
|
||||||
|
InputStream resource = plugin.getResource("jenkins.yml");
|
||||||
|
if (resource == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
try (InputStreamReader reader = new InputStreamReader(resource, StandardCharsets.UTF_8)) {
|
||||||
|
YamlConfig jenkinsConfig = YamlConfig.load(reader);
|
||||||
|
String jobUrl = jenkinsConfig.getString("JOB_URL");
|
||||||
|
if (jobUrl == null || jobUrl.equalsIgnoreCase("NONE")) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
String buildNumberString = jenkinsConfig.getString("BUILD_NUMBER");
|
||||||
|
if (buildNumberString == null || buildNumberString.equalsIgnoreCase("NONE")) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
int lastStableBuild = JenkinsUtils.getLastStableBuild(jobUrl, null, null);
|
||||||
|
int buildNumber = Integer.parseInt(buildNumberString);
|
||||||
|
int version = lastStableBuild - buildNumber;
|
||||||
|
if (version <= 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
String pluginName = plugin.getName();
|
||||||
|
sender.sendMessage(String.format("§a检测到服务器内安装的 %s 插件有 %d 个版本更新", pluginName, version));
|
||||||
|
sender.sendMessage(String.format("§b下载链接: &b&n&l%s", jobUrl));
|
||||||
|
} catch (IOException ignored) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onLoad() {
|
public void onLoad() {
|
||||||
instance = this;
|
instance = this;
|
||||||
@@ -107,10 +148,13 @@ public class HamsterCorePlugin extends JavaPlugin {
|
|||||||
logger.info("已注册 CallbackListener");
|
logger.info("已注册 CallbackListener");
|
||||||
Bukkit.getPluginManager().registerEvents(DebugListener.INSTANCE, this);
|
Bukkit.getPluginManager().registerEvents(DebugListener.INSTANCE, this);
|
||||||
logger.info("已注册 DebugListener");
|
logger.info("已注册 DebugListener");
|
||||||
|
Bukkit.getPluginManager().registerEvents(JenkinsUpdateListener.INSTANCE, this);
|
||||||
|
logger.info("已注册 JenkinsUpdateListener");
|
||||||
long time = System.currentTimeMillis() - start;
|
long time = System.currentTimeMillis() - start;
|
||||||
sync(() -> {
|
sync(() -> {
|
||||||
PointAPI.reloadPlayerPointAPIHook();
|
PointAPI.reloadPlayerPointAPIHook();
|
||||||
VaultAPI.reloadVaultHook();
|
VaultAPI.reloadVaultHook();
|
||||||
|
showUpdate(Bukkit.getConsoleSender());
|
||||||
});
|
});
|
||||||
logger.info("仓鼠核心启动完成,总计耗时 " + time + " ms");
|
logger.info("仓鼠核心启动完成,总计耗时 " + time + " ms");
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,30 @@
|
|||||||
|
package cn.hamster3.mc.plugin.core.bukkit.listener;
|
||||||
|
|
||||||
|
import cn.hamster3.mc.plugin.core.bukkit.HamsterCorePlugin;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.event.EventHandler;
|
||||||
|
import org.bukkit.event.Listener;
|
||||||
|
import org.bukkit.event.player.PlayerJoinEvent;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class JenkinsUpdateListener implements Listener {
|
||||||
|
public static final JenkinsUpdateListener INSTANCE = new JenkinsUpdateListener();
|
||||||
|
public static HashSet<UUID> SHOWED = new HashSet<>();
|
||||||
|
|
||||||
|
private JenkinsUpdateListener() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler(ignoreCancelled = true)
|
||||||
|
public void onPlayerJoin(PlayerJoinEvent event) {
|
||||||
|
Player player = event.getPlayer();
|
||||||
|
if (!player.hasPermission("hamster.core.admin")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!SHOWED.add(player.getUniqueId())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
HamsterCorePlugin.showUpdate(player);
|
||||||
|
}
|
||||||
|
}
|
@@ -2,11 +2,21 @@ package cn.hamster3.mc.plugin.core.bungee;
|
|||||||
|
|
||||||
import cn.hamster3.mc.plugin.core.bungee.api.CoreBungeeAPI;
|
import cn.hamster3.mc.plugin.core.bungee.api.CoreBungeeAPI;
|
||||||
import cn.hamster3.mc.plugin.core.common.api.CoreAPI;
|
import cn.hamster3.mc.plugin.core.common.api.CoreAPI;
|
||||||
|
import cn.hamster3.mc.plugin.core.common.config.YamlConfig;
|
||||||
|
import cn.hamster3.mc.plugin.core.common.util.JenkinsUtils;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import net.kyori.adventure.platform.bungeecord.BungeeAudiences;
|
import net.kyori.adventure.platform.bungeecord.BungeeAudiences;
|
||||||
|
import net.md_5.bungee.api.CommandSender;
|
||||||
|
import net.md_5.bungee.api.ProxyServer;
|
||||||
|
import net.md_5.bungee.api.chat.TextComponent;
|
||||||
import net.md_5.bungee.api.plugin.Plugin;
|
import net.md_5.bungee.api.plugin.Plugin;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.StandardCopyOption;
|
import java.nio.file.StandardCopyOption;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
@@ -56,6 +66,7 @@ public class HamsterCorePlugin extends Plugin {
|
|||||||
logger.info("已创建 AudienceProvider");
|
logger.info("已创建 AudienceProvider");
|
||||||
long time = System.currentTimeMillis() - start;
|
long time = System.currentTimeMillis() - start;
|
||||||
logger.info("仓鼠核心启动完成,总计耗时 " + time + " ms");
|
logger.info("仓鼠核心启动完成,总计耗时 " + time + " ms");
|
||||||
|
showUpdate(ProxyServer.getInstance().getConsole());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -73,4 +84,40 @@ public class HamsterCorePlugin extends Plugin {
|
|||||||
long time = System.currentTimeMillis() - start;
|
long time = System.currentTimeMillis() - start;
|
||||||
logger.info("仓鼠核心已关闭,总计耗时 " + time + " ms");
|
logger.info("仓鼠核心已关闭,总计耗时 " + time + " ms");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void showUpdate(@NotNull CommandSender sender) {
|
||||||
|
ProxyServer.getInstance().getScheduler().runAsync(HamsterCorePlugin.getInstance(), () -> {
|
||||||
|
for (Plugin plugin : ProxyServer.getInstance().getPluginManager().getPlugins()) {
|
||||||
|
InputStream resource = plugin.getResourceAsStream("jenkins.yml");
|
||||||
|
if (resource == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
try (InputStreamReader reader = new InputStreamReader(resource, StandardCharsets.UTF_8)) {
|
||||||
|
YamlConfig jenkinsConfig = YamlConfig.load(reader);
|
||||||
|
String jobUrl = jenkinsConfig.getString("JOB_URL");
|
||||||
|
if (jobUrl == null || jobUrl.equalsIgnoreCase("NONE")) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
String buildNumberString = jenkinsConfig.getString("BUILD_NUMBER");
|
||||||
|
if (buildNumberString == null || buildNumberString.equalsIgnoreCase("NONE")) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
int lastStableBuild = JenkinsUtils.getLastStableBuild(jobUrl, null, null);
|
||||||
|
int buildNumber = Integer.parseInt(buildNumberString);
|
||||||
|
int version = lastStableBuild - buildNumber;
|
||||||
|
if (version <= 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
String pluginName = plugin.getDescription().getName();
|
||||||
|
sender.sendMessage(TextComponent.fromLegacyText(
|
||||||
|
String.format("§a检测到服务器内安装的 %s 插件有 %d 个版本更新", pluginName, version)
|
||||||
|
));
|
||||||
|
sender.sendMessage(TextComponent.fromLegacyText(
|
||||||
|
String.format("§b下载链接: &b&n&l%s", jobUrl)
|
||||||
|
));
|
||||||
|
} catch (IOException ignored) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -7,7 +7,7 @@ import java.io.*;
|
|||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings({"unused", "VulnerableCodeUsages"})
|
||||||
public class YamlConfig extends ConfigSection {
|
public class YamlConfig extends ConfigSection {
|
||||||
public static final Yaml YAML_LOADER = new Yaml();
|
public static final Yaml YAML_LOADER = new Yaml();
|
||||||
|
|
||||||
@@ -22,11 +22,15 @@ public class YamlConfig extends ConfigSection {
|
|||||||
public static YamlConfig load(@NotNull File file) throws IOException {
|
public static YamlConfig load(@NotNull File file) throws IOException {
|
||||||
try (FileInputStream stream = new FileInputStream(file)) {
|
try (FileInputStream stream = new FileInputStream(file)) {
|
||||||
try (InputStreamReader reader = new InputStreamReader(stream, StandardCharsets.UTF_8)) {
|
try (InputStreamReader reader = new InputStreamReader(stream, StandardCharsets.UTF_8)) {
|
||||||
|
return load(reader);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static YamlConfig load(@NotNull Reader reader) {
|
||||||
Map<String, Object> load = YAML_LOADER.load(reader);
|
Map<String, Object> load = YAML_LOADER.load(reader);
|
||||||
return new YamlConfig(load);
|
return new YamlConfig(load);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void save(@NotNull File file) throws IOException {
|
public void save(@NotNull File file) throws IOException {
|
||||||
try (FileOutputStream stream = new FileOutputStream(file)) {
|
try (FileOutputStream stream = new FileOutputStream(file)) {
|
||||||
|
@@ -0,0 +1,41 @@
|
|||||||
|
package cn.hamster3.mc.plugin.core.common.util;
|
||||||
|
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
import com.google.gson.JsonParser;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.net.HttpURLConnection;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.Base64;
|
||||||
|
|
||||||
|
public final class JenkinsUtils {
|
||||||
|
private static final JsonParser JSON_PARSER = new JsonParser();
|
||||||
|
|
||||||
|
private JenkinsUtils() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int getLastStableBuild(@NotNull String jobUrl, @Nullable String username, @Nullable String apiToken) throws IOException {
|
||||||
|
URL url = new URL(jobUrl + "api/json");
|
||||||
|
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
|
||||||
|
connection.setDoInput(true);
|
||||||
|
connection.setRequestMethod("GET");
|
||||||
|
if (username != null && apiToken != null) {
|
||||||
|
String token = username + ":" + apiToken;
|
||||||
|
String base64 = Base64.getEncoder().encodeToString(token.getBytes(StandardCharsets.UTF_8));
|
||||||
|
connection.setRequestProperty("Authorization", "Basic " + base64);
|
||||||
|
}
|
||||||
|
connection.connect();
|
||||||
|
try (InputStream stream = connection.getInputStream()) {
|
||||||
|
try (InputStreamReader reader = new InputStreamReader(stream)) {
|
||||||
|
JsonObject object = JSON_PARSER.parse(reader).getAsJsonObject();
|
||||||
|
JsonObject lastStableBuild = object.getAsJsonObject("lastStableBuild");
|
||||||
|
return lastStableBuild.get("number").getAsInt();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user