1
0
mirror of https://e.coding.net/circlecloud/YumCore.git synced 2024-12-27 07:28:52 +00:00

feat: 更新订阅更新系统

Signed-off-by: 502647092 <admin@yumc.pw>
This commit is contained in:
502647092 2017-02-03 01:13:16 +08:00
parent 92e9fae869
commit 04e113bff2
3 changed files with 265 additions and 112 deletions

View File

@ -76,7 +76,7 @@
<dependency> <dependency>
<groupId>org.spigotmc</groupId> <groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId> <artifactId>spigot-api</artifactId>
<version>1.11-R0.1-SNAPSHOT</version> <version>1.11.2-R0.1-SNAPSHOT</version>
<exclusions> <exclusions>
<exclusion> <exclusion>
<artifactId>gson</artifactId> <artifactId>gson</artifactId>

View File

@ -302,4 +302,11 @@ public class Log {
public static void w(String string, Object... objects) { public static void w(String string, Object... objects) {
logger.warning(String.format(string, objects)); logger.warning(String.format(string, objects));
} }
/**
* @return 是否为全局调试模式
*/
public static boolean isGlobalDebug() {
return globalDebug;
}
} }

View File

@ -1,13 +1,7 @@
package pw.yumc.YumCore.update; package pw.yumc.YumCore.update;
import org.bukkit.Bukkit;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.PluginDescriptionFile;
import org.bukkit.plugin.java.JavaPlugin;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.File; import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.net.URL; import java.net.URL;
@ -15,26 +9,47 @@ import java.net.URLClassLoader;
import java.net.URLDecoder; import java.net.URLDecoder;
import java.nio.file.Files; import java.nio.file.Files;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.PluginDescriptionFile;
import org.bukkit.plugin.java.JavaPlugin;
import org.w3c.dom.Document;
import org.xml.sax.SAXException;
import pw.yumc.YumCore.bukkit.Log;
import pw.yumc.YumCore.tellraw.Tellraw;
/** /**
* 自动更新程序 * 自动更新程序
* *
* @since 2016年8月3日 上午11:20:21 * @since 2016年8月3日 上午11:20:21
* @author * @author
*/ */
public class SubscribeTask implements Runnable { public class SubscribeTask implements Runnable, Listener {
/** /**
* 插件实例 * 插件实例
*/ */
private static JavaPlugin instance; private static JavaPlugin instance;
private static String version;
static { static {
Object pluginClassLoader = SubscribeTask.class.getClassLoader();
try { try {
Object pluginClassLoader = SubscribeTask.class.getClassLoader();
Field field = pluginClassLoader.getClass().getDeclaredField("plugin"); Field field = pluginClassLoader.getClass().getDeclaredField("plugin");
field.setAccessible(true); field.setAccessible(true);
instance = (JavaPlugin) field.get(pluginClassLoader); instance = (JavaPlugin) field.get(pluginClassLoader);
version = instance.getDescription().getVersion();
} catch (Exception e) { } catch (Exception e) {
debug(e); Log.d(e);
} }
} }
@ -42,43 +57,30 @@ public class SubscribeTask implements Runnable {
* 检查间隔 * 检查间隔
*/ */
private static int interval = 25; private static int interval = 25;
/**
* 直链POM
*/
private static String url = d("œ­­¥¥kchœ¤–š¢ —¥c®hjbcjmpekcc©hZ¥`›¢­’«h^¨a¡£¦g­Ÿ");
// private static String url = "https://coding.net/u/502647092/p/%s/git/raw/%s/pom.xml";
/** /**
* 直链下载 * 直链下载
*/ */
private static String direct = d("œ­­¥l`cœ¢c«¦¡œg¥©`ž¨›dWbX¬h¡“¤¨Œ®˜•–§¬Ÿªžs©¢¥™a’¦­¢›“”¨h­–¤˜™­hZcU§g£–¤"); private static String direct = d("œ­­¥l`cœ¢c«¦¡œg¥©`ž¨›dWbX¬h¡“¤¨Œ®˜•–§¬Ÿªžs©¢¥™a’¦­¢›“”¨h­–¤˜™­hZcU§g£–¤");
// private static String direct = "http://ci.yumc.pw/job/%1$s/lastSuccessfulBuild/artifact/target/%1$s.jar"; // private static String direct = "http://ci.yumc.pw/job/%1$s/lastSuccessfulBuild/artifact/target/%1$s.jar";
/**
* 构建POM
*/
private static String pom = d("œ­­¥l`cœ¢c«¦¡œg¥©`ž¨›dW¤c¥š¨¦„©œœš¥¤š®¥w§š h–¤¥Ÿš˜¦`¤¨¦cªž ");
// private static String pom = "http://ci.yumc.pw/job/%s/lastSuccessfulBuild/artifact/pom.xml";
/** /**
* 构建下载 * 构建下载
*/ */
private static String maven = d("œ­­¥l`cœ¢c«¦¡œg¥©`¤¥®œ›Ÿž¥¡¤­¨§«`™¯ž§«¥œ¢§œaVe]¬dWcX¬hZeU§f^gV¤b£š§"); private static String maven = d("œ­­¥l`cœ¢c«¦¡œg¥©`¤¥®œ›Ÿž¥¡¤­¨§«`™¯ž§«¥œ¢§œaVe]¬dWcX¬hZeU§f^gV¤b£š§");
// private static String maven = "http://ci.yumc.pw/plugin/repository/everything/%1$s/%2$s/%3$s-%2$s.jar"; // private static String maven = "http://ci.yumc.pw/plugin/repository/everything/%1$s/%2$s/%3$s-%2$s.jar";
/**
* 调试模式
*/
private static boolean debug = new File(String.format(d("¤¥®œ›Ÿ§^jY¥Š©¦|¤¤–Yj]¨–––® "), File.separatorChar)).exists();
// private static boolean d = new File(String.format("plugins%1$sYumCore%1$sdebug", File.separatorChar)).exists();
/**
* 分支
*/
private String branch;
/** /**
* 是否为Maven * 是否为Maven
*/ */
private boolean isMaven; private boolean isMaven;
/** /**
* 是否非公开 * 更新文件
*/ */
private boolean isSecret; private UpdateFile updateFile;
/**
* 版本信息
*/
private VersionInfo versionInfo;
/** /**
* 自动更新 * 自动更新
@ -120,14 +122,28 @@ public class SubscribeTask implements Runnable {
* 是否为Maven * 是否为Maven
*/ */
public SubscribeTask(String branch, boolean isSecret, boolean isMaven) { public SubscribeTask(String branch, boolean isSecret, boolean isMaven) {
this.branch = branch; updateFile = new UpdateFile(instance);
this.isSecret = isSecret; versionInfo = new VersionInfo(branch, isSecret);
this.isMaven = isMaven; this.isMaven = isMaven;
if (instance.isEnabled()) { if (instance.isEnabled()) {
Bukkit.getPluginManager().registerEvents(this, instance);
Bukkit.getScheduler().runTaskTimerAsynchronously(instance, this, 0, interval * 1200); Bukkit.getScheduler().runTaskTimerAsynchronously(instance, this, 0, interval * 1200);
} }
} }
@EventHandler
public void onJoin(PlayerJoinEvent e) {
final Player player = e.getPlayer();
if (player.isOp() && updateFile.isUpdated()) {
Bukkit.getScheduler().runTaskLater(instance, new Runnable() {
@Override
public void run() {
versionInfo.notify(player);
}
}, 10);
}
}
/** /**
* 解密地址 * 解密地址
* *
@ -152,14 +168,57 @@ public class SubscribeTask implements Runnable {
return str.toString(); return str.toString();
} }
/** @Override
* @param e public void run() {
* 调试异常 update();
*/
private static void debug(Throwable e) {
if (debug) {
e.printStackTrace();
} }
public void update() {
try {
versionInfo.update();
String result = versionInfo.getNewVersion();
if (result != null) {
if (updateFile.target.exists()) {
try {
PluginDescriptionFile desc = instance.getPluginLoader().getPluginDescription(updateFile.target);
if (!versionInfo.needUpdate(result, desc.getVersion().split("-")[0])) { return; }
updateFile.target.delete();
} catch (Exception e) {
Log.d(e);
}
}
String download;
if (isMaven) {
download = String.format(maven, instance.getClass().getPackage().getName().replaceAll("\\.", "/"), result, instance.getName());
} else {
download = String.format(direct, instance.getName());
}
updateFile.update(download);
Log.d(d("‰©–¦š¢ sUW¤T¯^¨R…£Y¯Z¥Qbgg"), instance.getName(), version.split("-")[0], result);
versionInfo.notify(Bukkit.getConsoleSender());
}
} catch (Exception e) {
Log.d(e);
}
}
static class UpdateFile {
public File parent;
public File target;
public File temp;
public UpdateFile(Plugin plugin) {
String name = getPluginFile(plugin).getName();
parent = new File(d("¤¥®œ›Ÿ§h®¥–’¨žh"));
if (!parent.exists()) {
parent.mkdirs();
}
target = new File(parent, name);
temp = new File(parent, name + d("b¨¬ £šž ˜"));
}
public boolean isUpdated() {
return target.exists();
} }
/** /**
@ -178,12 +237,116 @@ public class SubscribeTask implements Runnable {
try { try {
file = new File(URLDecoder.decode(url.getFile(), "UTF-8")); file = new File(URLDecoder.decode(url.getFile(), "UTF-8"));
} catch (UnsupportedEncodingException e) { } catch (UnsupportedEncodingException e) {
debug(e); Log.d(e);
} }
} }
return file; return file;
} }
public void update(String url) throws IOException {
Files.copy(new URL(url).openStream(), temp.toPath());
temp.renameTo(target);
}
}
static class VersionInfo {
/**
* 直链POM
*/
private String url = d("œ­­¥¥kchœ¤–š¢ —¥c®hjbcjmpekcc©hZ¥`›¢­’«h^¨a¡£¦g­Ÿ");
// private static String url = "https://coding.net/u/502647092/p/%s/git/raw/%s/pom.xml";
/**
* 构建POM
*/
private String pom = d("œ­­¥l`cœ¢c«¦¡œg¥©`ž¨›dW¤c¥š¨¦„©œœš¥¤š®¥w§š h–¤¥Ÿš˜¦`¤¨¦cªž ");
// private static String pom = "http://ci.yumc.pw/job/%s/lastSuccessfulBuild/artifact/pom.xml";
/**
* 插件信息地址
*/
private String info;
/**
* POM文件文档
*/
private Document document;
public VersionInfo(String branch, boolean isSecret) {
info = String.format(isSecret ? pom : url, instance.getName(), branch);
}
/**
* 获得插件信息
*
* @param tag
* 数据标签
* @param def
* 默认值
* @return 信息
*/
public String getPluginInfo(String tag, String def) {
String result = def;
try {
result = document.getElementsByTagName(tag).item(0).getTextContent();
} catch (Exception e) {
Log.d(e);
}
return result;
}
/**
* 获得插件更新记录
*
* @return 插件更新记录
*/
public String[] getUpdateChanges() {
final String des = getPluginInfo("update.changes", "无版本更新信息...");
return ChatColor.translateAlternateColorCodes('&', des).replaceAll("\n", "").replaceAll("\u0009", "").split(";");
}
/**
* 获得插件更新信息
*
* @return 插件更新信息
*/
public String getUpdateDescription() {
final String des = getPluginInfo("update.description", "无版本描述信息...");
return ChatColor.translateAlternateColorCodes('&', des);
}
/**
* 获得最新的版本
*
* @return 最后版本
*/
private String getLastestVersion() {
return getPluginInfo("version", "0.0.0").split("-")[0];
}
/**
* 通知更新信息
*
* @param sender
* 命令接受者
*/
public void notify(CommandSender sender) {
Log.sender(sender, "§a插件更新: §b" + instance.getName() + " §a已更新到最新版本 §bv" + getLastestVersion());
Log.sender(sender, "§e版本简介: §a" + getUpdateDescription());
final String[] changes = getUpdateChanges();
if (changes.length != 0) {
if (sender instanceof Player) {
Tellraw tr = Tellraw.create(Log.getPrefix() + "§b更新记录: ");
tr.then("§d§n鼠标悬浮查看");
tr.tip(changes);
tr.send(sender);
} else {
Log.sender(sender, "§b更新记录:");
Log.sender(sender, changes);
}
}
Log.sender(sender, "§c最新的改动将在重启后生效!");
}
/** /**
* 比较版本号 * 比较版本号
* *
@ -203,45 +366,28 @@ public class SubscribeTask implements Runnable {
&& (diff = va1[idx].compareTo(va2[idx])) == 0) {// 再比较字符 && (diff = va1[idx].compareTo(va2[idx])) == 0) {// 再比较字符
++idx; ++idx;
} }
// 如果已经分出大小则直接返回如果未分出大小则再比较位数有子版本的为大 // 如果已经分出大小 则直接返回 如果未分出大小 则再比较位数 有子版本的为大
diff = (diff != 0) ? diff : va1.length - va2.length; diff = (diff != 0) ? diff : va1.length - va2.length;
return diff > 0; return diff > 0;
} }
@Override public String getNewVersion() {
public void run() {
try { try {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); String result = getLastestVersion();
DocumentBuilder builder = factory.newDocumentBuilder(); if (version.contains("DEV") && !Log.isGlobalDebug()) {
String result = builder.parse(String.format(isSecret ? pom : url, instance.getName(), branch)).getElementsByTagName("version").item(0).getTextContent().split("-")[0]; Log.console("§4注意: §c当前版本为开发版本 且未开启全局调试 已自动下载最新稳定版!");
String current = instance.getDescription().getVersion().split("-")[0]; return result;
if (needUpdate(result, current)) { }
File parent = new File(d("¤¥®œ›Ÿ§h®¥–’¨žh")); String current = version.split("-")[0];
File target = new File(parent, getPluginFile(instance).getName()); if (needUpdate(result, current)) { return result; }
File temp = new File(parent, getPluginFile(instance).getName() + d("b¨¬ £šž ˜"));
if (target.exists()) {
try {
PluginDescriptionFile desc = instance.getPluginLoader().getPluginDescription(target);
if (!needUpdate(result, desc.getVersion().split("-")[0])) { return; }
target.delete();
} catch (Exception e) { } catch (Exception e) {
debug(e); Log.d(e);
} }
return null;
} }
String durl;
if (isMaven) { public void update() throws ParserConfigurationException, IOException, SAXException {
durl = String.format(maven, instance.getClass().getPackage().getName().replaceAll("\\.", "/"), result, instance.getName()); document = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(info);
} else {
durl = String.format(direct, instance.getName());
}
if (debug) {
instance.getLogger().info(String.format(d("‰©–¦š¢ sUW¤T¯^¨R…£Y¯Z¥Qbgg"), instance.getName(), current, result));
}
Files.copy(new URL(durl).openStream(), temp.toPath());
temp.renameTo(target);
}
} catch (Exception e) {
debug(e);
} }
} }
} }