From d4b5efd29b9691d14ecd8eb938d52b1f202e7e95 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E6=B3=A0=E8=BE=B0?= <2154818001@qq.com>
Date: Tue, 30 Aug 2022 22:31:42 +0800
Subject: [PATCH] init
---
.gitignore | 96 ++++++++++++++++++-
pom.xml | 91 ++++++++++++++++++
.../lingshttputils/LingsHTTPUtils.java | 54 +++++++++++
.../asyncworkers/AsyncWorkers.java | 47 +++++++++
.../asyncworkers/WorkerOptions.java | 61 ++++++++++++
.../lingshttputils/commands/Commands.java | 42 ++++++++
.../lingshttputils/commands/HelpCommand.java | 21 ++++
.../commands/ReloadCommand.java | 35 +++++++
.../lingshttputils/commands/TabComplete.java | 31 ++++++
.../commands/WorkerOptionCommands.java | 51 ++++++++++
.../placeholderapi/PlaceholderAPI.java | 82 ++++++++++++++++
.../requesters/HTTPRequester.java | 66 +++++++++++++
.../lingshttputils/senders/MessageSender.java | 21 ++++
.../lingshttputils/utils/JsonUtils.java | 32 +++++++
src/main/resources/config.yml | 43 +++++++++
src/main/resources/plugin.yml | 19 ++++
16 files changed, 789 insertions(+), 3 deletions(-)
create mode 100644 pom.xml
create mode 100644 src/main/java/cn/lingsmc/lingshttputils/LingsHTTPUtils.java
create mode 100644 src/main/java/cn/lingsmc/lingshttputils/asyncworkers/AsyncWorkers.java
create mode 100644 src/main/java/cn/lingsmc/lingshttputils/asyncworkers/WorkerOptions.java
create mode 100644 src/main/java/cn/lingsmc/lingshttputils/commands/Commands.java
create mode 100644 src/main/java/cn/lingsmc/lingshttputils/commands/HelpCommand.java
create mode 100644 src/main/java/cn/lingsmc/lingshttputils/commands/ReloadCommand.java
create mode 100644 src/main/java/cn/lingsmc/lingshttputils/commands/TabComplete.java
create mode 100644 src/main/java/cn/lingsmc/lingshttputils/commands/WorkerOptionCommands.java
create mode 100644 src/main/java/cn/lingsmc/lingshttputils/placeholderapi/PlaceholderAPI.java
create mode 100644 src/main/java/cn/lingsmc/lingshttputils/requesters/HTTPRequester.java
create mode 100644 src/main/java/cn/lingsmc/lingshttputils/senders/MessageSender.java
create mode 100644 src/main/java/cn/lingsmc/lingshttputils/utils/JsonUtils.java
create mode 100644 src/main/resources/config.yml
create mode 100644 src/main/resources/plugin.yml
diff --git a/.gitignore b/.gitignore
index a1c2a23..4788b4b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,13 @@
+# User-specific stuff
+.idea/
+
+*.iml
+*.ipr
+*.iws
+
+# IntelliJ
+out/
+
# Compiled class file
*.class
@@ -7,9 +17,6 @@
# BlueJ files
*.ctxt
-# Mobile Tools for Java (J2ME)
-.mtj.tmp/
-
# Package Files #
*.jar
*.war
@@ -21,3 +28,86 @@
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
+
+*~
+
+# temporary files which can be created if a process still has a handle open of a deleted file
+.fuse_hidden*
+
+# KDE directory preferences
+.directory
+
+# Linux trash folder which might appear on any partition or disk
+.Trash-*
+
+# .nfs files are created when an open file is removed but is still being accessed
+.nfs*
+
+# General
+.DS_Store
+.AppleDouble
+.LSOverride
+
+# Icon must end with two \r
+Icon
+
+# Thumbnails
+._*
+
+# Files that might appear in the root of a volume
+.DocumentRevisions-V100
+.fseventsd
+.Spotlight-V100
+.TemporaryItems
+.Trashes
+.VolumeIcon.icns
+.com.apple.timemachine.donotpresent
+
+# Directories potentially created on remote AFP share
+.AppleDB
+.AppleDesktop
+Network Trash Folder
+Temporary Items
+.apdisk
+
+# Windows thumbnail cache files
+Thumbs.db
+Thumbs.db:encryptable
+ehthumbs.db
+ehthumbs_vista.db
+
+# Dump file
+*.stackdump
+
+# Folder config file
+[Dd]esktop.ini
+
+# Recycle Bin used on file shares
+$RECYCLE.BIN/
+
+# Windows Installer files
+*.cab
+*.msi
+*.msix
+*.msm
+*.msp
+
+# Windows shortcuts
+*.lnk
+
+target/
+
+pom.xml.tag
+pom.xml.releaseBackup
+pom.xml.versionsBackup
+pom.xml.next
+
+release.properties
+dependency-reduced-pom.xml
+buildNumber.properties
+.mvn/timing.properties
+.mvn/wrapper/maven-wrapper.jar
+.flattened-pom.xml
+
+# Common working directory
+run/
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..9074fe1
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,91 @@
+
+
+ 4.0.0
+
+ cn.lingsmc
+ LingsHTTPUtils
+ 1.0
+ jar
+
+ LingsHTTPUtils
+
+ Connect website text with PAPI.
+
+ 1.8
+ UTF-8
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.8.1
+
+ ${java.version}
+ ${java.version}
+
+
+
+ org.apache.maven.plugins
+ maven-shade-plugin
+ 3.2.4
+
+
+ package
+
+ shade
+
+
+ false
+
+
+
+
+
+
+
+ src/main/resources
+ true
+
+
+
+
+
+
+ spigotmc-repo
+ https://hub.spigotmc.org/nexus/content/repositories/snapshots/
+
+
+ sonatype
+ https://oss.sonatype.org/content/groups/public/
+
+
+ placeholderapi
+ https://repo.extendedclip.com/content/repositories/placeholderapi/
+
+
+
+
+
+ org.spigotmc
+ spigot-api
+ 1.12-R0.1-SNAPSHOT
+ provided
+
+
+ org.projectlombok
+ lombok
+ 1.18.24
+ provided
+
+
+ me.clip
+ placeholderapi
+ 2.11.2
+ provided
+
+
+
diff --git a/src/main/java/cn/lingsmc/lingshttputils/LingsHTTPUtils.java b/src/main/java/cn/lingsmc/lingshttputils/LingsHTTPUtils.java
new file mode 100644
index 0000000..01d7253
--- /dev/null
+++ b/src/main/java/cn/lingsmc/lingshttputils/LingsHTTPUtils.java
@@ -0,0 +1,54 @@
+package cn.lingsmc.lingshttputils;
+
+
+import cn.lingsmc.lingshttputils.asyncworkers.WorkerOptions;
+import cn.lingsmc.lingshttputils.commands.Commands;
+import cn.lingsmc.lingshttputils.commands.TabComplete;
+import cn.lingsmc.lingshttputils.placeholderapi.PlaceholderAPI;
+import com.google.common.collect.Maps;
+import lombok.Getter;
+import org.bukkit.Bukkit;
+import org.bukkit.command.PluginCommand;
+import org.bukkit.plugin.java.JavaPlugin;
+
+import java.util.Map;
+
+
+/**
+ * @author Crsuh2er0
+ * @date 2022/8/30
+ * @apiNote
+ */
+public final class LingsHTTPUtils extends JavaPlugin {
+ @Getter
+ private static LingsHTTPUtils instance;
+
+ @Getter
+ private final Map httpData = Maps.newConcurrentMap();
+
+ @Override
+ public void onLoad() {
+ instance = this;
+ saveDefaultConfig();
+ getConfig().options().copyDefaults(true);
+ }
+
+ @Override
+ public void onEnable() {
+ // Plugin startup logic
+ if (Bukkit.getPluginManager().getPlugin("PlaceholderAPI") != null) {
+ new PlaceholderAPI(this).register();
+ }
+ final PluginCommand command = this.getCommand(instance.getName());
+ command.setExecutor(new Commands());
+ command.setTabCompleter(new TabComplete());
+ // 运行Cycle worker
+ WorkerOptions.runWorkers();
+ }
+
+ @Override
+ public void onDisable() {
+ // Plugin shutdown logic
+ WorkerOptions.stopWorkers();
+ }
+}
diff --git a/src/main/java/cn/lingsmc/lingshttputils/asyncworkers/AsyncWorkers.java b/src/main/java/cn/lingsmc/lingshttputils/asyncworkers/AsyncWorkers.java
new file mode 100644
index 0000000..8d43cdc
--- /dev/null
+++ b/src/main/java/cn/lingsmc/lingshttputils/asyncworkers/AsyncWorkers.java
@@ -0,0 +1,47 @@
+package cn.lingsmc.lingshttputils.asyncworkers;
+
+import cn.lingsmc.lingshttputils.LingsHTTPUtils;
+import cn.lingsmc.lingshttputils.requesters.HTTPRequester;
+import cn.lingsmc.lingshttputils.utils.JsonUtils;
+import lombok.Getter;
+import org.bukkit.Bukkit;
+import org.bukkit.configuration.file.FileConfiguration;
+import org.bukkit.scheduler.BukkitRunnable;
+
+
+/**
+ * @author Crsuh2er0
+ * @date 2022/8/30
+ * @apiNote
+ */
+public class AsyncWorkers {
+ @Getter
+ private final FileConfiguration config = LingsHTTPUtils.getInstance().getConfig();
+ @Getter
+ Runnable taskB;
+ @Getter
+ Runnable task;
+
+ public void asyncworker(String module, int reqTime, String url, String method, int refInterval, String[] keys) {
+ task = new BukkitRunnable() {
+ @Override
+ public void run() {
+ String res = HTTPRequester.request(url, reqTime, method);
+ if (res == null) {
+ return;
+ }
+ if ("json".equals(config.getString(String.format("%s.mode", module)))) {
+ res = JsonUtils.getValue(JsonUtils.parseStr(res), keys, 0);
+ }
+ LingsHTTPUtils.getInstance().getHttpData().put(module, res);
+ try {
+ Thread.sleep(refInterval);
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ Bukkit.getScheduler().runTaskAsynchronously(Bukkit.getPluginManager().getPlugin(LingsHTTPUtils.getInstance().getName()), task);
+ }
+ };
+ Bukkit.getScheduler().runTaskAsynchronously(Bukkit.getPluginManager().getPlugin(LingsHTTPUtils.getInstance().getName()), task);
+ }
+}
diff --git a/src/main/java/cn/lingsmc/lingshttputils/asyncworkers/WorkerOptions.java b/src/main/java/cn/lingsmc/lingshttputils/asyncworkers/WorkerOptions.java
new file mode 100644
index 0000000..bb37ab9
--- /dev/null
+++ b/src/main/java/cn/lingsmc/lingshttputils/asyncworkers/WorkerOptions.java
@@ -0,0 +1,61 @@
+package cn.lingsmc.lingshttputils.asyncworkers;
+
+import cn.lingsmc.lingshttputils.LingsHTTPUtils;
+import lombok.Getter;
+import org.bukkit.configuration.file.FileConfiguration;
+
+import java.util.Objects;
+import java.util.Set;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+/**
+ * @author Crsuh2er0
+ * @date 2022/8/30
+ * @apiNote
+ */
+public class WorkerOptions {
+ @Getter
+ static boolean started = true;
+ private static ExecutorService newFixedThreadPool;
+
+
+ public WorkerOptions() {
+ }
+
+ public static void runWorkers() {
+ started = true;
+ newFixedThreadPool = Executors.newFixedThreadPool(2);
+ Set modules = LingsHTTPUtils.getInstance().getConfig().getKeys(false);
+ FileConfiguration config = LingsHTTPUtils.getInstance().getConfig();
+ for (String module : modules) {
+ if (Objects.equals(config.getString(String.format("%s.reqMode", module)), "Cycle")) {
+ // 一定要为每个module设置一个worker
+ AsyncWorkers asyncWorkers = new AsyncWorkers();
+ final int reqTime = config.getInt(String.format("%s.reqTime", module));
+ final String url = config.getString(String.format("%s.url", module));
+ final String method;
+ final int refInterval = config.getInt(String.format("%s.refInterval", module));
+ if (config.getString(String.format("%s.method", module)) != null) {
+ method = config.getString(String.format("%s.method", module));
+ } else {
+ method = "GET";
+ }
+ String[] keys = new String[0];
+ if ("json".equals(config.getString(String.format("%s.mode", module)))) {
+ keys = config.getString(String.format("%s.key", module)).split("\\.");
+ }
+ String[] finalKeys = keys;
+ Runnable runnable = () -> asyncWorkers.asyncworker(module, reqTime, url, method, refInterval, finalKeys);
+ LingsHTTPUtils.getInstance().getLogger().info("尝试启动Cycle Worker...");
+ newFixedThreadPool.execute(runnable);
+ }
+ }
+ }
+
+ public static void stopWorkers() {
+ LingsHTTPUtils.getInstance().getLogger().info("尝试关闭Cycle Worker...");
+ newFixedThreadPool.shutdownNow();
+ started = false;
+ }
+}
diff --git a/src/main/java/cn/lingsmc/lingshttputils/commands/Commands.java b/src/main/java/cn/lingsmc/lingshttputils/commands/Commands.java
new file mode 100644
index 0000000..99942e7
--- /dev/null
+++ b/src/main/java/cn/lingsmc/lingshttputils/commands/Commands.java
@@ -0,0 +1,42 @@
+package cn.lingsmc.lingshttputils.commands;
+
+import cn.lingsmc.lingshttputils.LingsHTTPUtils;
+import org.bukkit.ChatColor;
+import org.bukkit.command.Command;
+import org.bukkit.command.CommandExecutor;
+import org.bukkit.command.CommandSender;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author Crsuh2er0
+ * @date 2022/8/30
+ * @apiNote
+ */
+public class Commands implements CommandExecutor {
+ static String helpMessage = String.format("%s未知命令!输入/lhu help查看命令列表!", ChatColor.RED);
+ static String rootMessage = String.format("%s此服务器正在运行 %s%s %s%s by %s %n%s命令列表: %s/lhu help", ChatColor.DARK_AQUA, ChatColor.AQUA, LingsHTTPUtils.getInstance().getName(), LingsHTTPUtils.getInstance().getDescription().getVersion(), ChatColor.DARK_AQUA, "§aC§br§cs§du§eh§a2§be§cr§d0", ChatColor.DARK_AQUA, ChatColor.AQUA);
+ static String permission = "lingshttputils.admin";
+
+ @Override
+ public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String @NotNull [] args) {
+ if (args.length < 1) {
+ sender.sendMessage(rootMessage);
+ return true;
+ }
+ switch (args[0]) {
+ case "reload":
+ ReloadCommand.reloadCommand(sender);
+ break;
+ case "help":
+ HelpCommand.helpCommand(sender);
+ break;
+ case "workers":
+ WorkerOptionCommands.workerOptionCommands(sender, args);
+ break;
+ default:
+ sender.sendMessage(helpMessage);
+ break;
+ }
+ return true;
+ }
+}
diff --git a/src/main/java/cn/lingsmc/lingshttputils/commands/HelpCommand.java b/src/main/java/cn/lingsmc/lingshttputils/commands/HelpCommand.java
new file mode 100644
index 0000000..a056f57
--- /dev/null
+++ b/src/main/java/cn/lingsmc/lingshttputils/commands/HelpCommand.java
@@ -0,0 +1,21 @@
+package cn.lingsmc.lingshttputils.commands;
+
+import org.bukkit.ChatColor;
+import org.bukkit.command.CommandSender;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author Crsuh2er0
+ * @date 2022/8/30
+ * @apiNote
+ */
+public class HelpCommand {
+ private HelpCommand() {
+ }
+
+ public static void helpCommand(@NotNull CommandSender sender) {
+ sender.sendMessage(String.format("%s%s----- LingsHTTPUtils指令 -----", ChatColor.DARK_AQUA, ChatColor.BOLD));
+ sender.sendMessage(String.format("%s/lhu workers %s启动/关闭Cycle Workers", ChatColor.AQUA, ChatColor.GREEN));
+ sender.sendMessage(String.format("%s/lhu reload %s重载插件", ChatColor.AQUA, ChatColor.GREEN));
+ }
+}
diff --git a/src/main/java/cn/lingsmc/lingshttputils/commands/ReloadCommand.java b/src/main/java/cn/lingsmc/lingshttputils/commands/ReloadCommand.java
new file mode 100644
index 0000000..ecb9206
--- /dev/null
+++ b/src/main/java/cn/lingsmc/lingshttputils/commands/ReloadCommand.java
@@ -0,0 +1,35 @@
+package cn.lingsmc.lingshttputils.commands;
+
+import cn.lingsmc.lingshttputils.LingsHTTPUtils;
+import cn.lingsmc.lingshttputils.asyncworkers.WorkerOptions;
+import org.bukkit.ChatColor;
+import org.bukkit.command.CommandSender;
+import org.jetbrains.annotations.NotNull;
+
+import java.io.File;
+
+/**
+ * @author Crsuh2er0
+ * @date 2022/8/30
+ * @apiNote
+ */
+public class ReloadCommand {
+ static LingsHTTPUtils plugin = LingsHTTPUtils.getInstance();
+
+ private ReloadCommand() {
+ }
+
+ public static void reloadCommand(@NotNull CommandSender sender) {
+ if (!sender.hasPermission(Commands.permission)) {
+ sender.sendMessage(String.format("%s你没有执行此命令的权限.", ChatColor.RED));
+ return;
+ }
+ WorkerOptions.stopWorkers();
+ File file = new File(plugin.getDataFolder(), "config.yml");
+ if (!file.exists()) {
+ plugin.saveDefaultConfig();
+ }
+ plugin.reloadConfig();
+ WorkerOptions.runWorkers();
+ }
+}
diff --git a/src/main/java/cn/lingsmc/lingshttputils/commands/TabComplete.java b/src/main/java/cn/lingsmc/lingshttputils/commands/TabComplete.java
new file mode 100644
index 0000000..7829148
--- /dev/null
+++ b/src/main/java/cn/lingsmc/lingshttputils/commands/TabComplete.java
@@ -0,0 +1,31 @@
+package cn.lingsmc.lingshttputils.commands;
+
+import org.bukkit.command.Command;
+import org.bukkit.command.CommandSender;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * @author Crsuh2er0
+ * @date 2022/8/30
+ * @apiNote
+ */
+public class TabComplete implements org.bukkit.command.TabCompleter {
+ @Override
+ public List onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias, @NotNull String[] args) {
+
+ final String[] root = new String[]{"workers", "help", "reload"};
+ final String[] worker = new String[]{"start", "stop"};
+
+ if (args.length <= 1) {
+ return Arrays.asList(root);
+ }
+ if (args.length <= 2 && root[0].equalsIgnoreCase(args[0])) {
+ return Arrays.asList(worker);
+ }
+ return Collections.emptyList();
+ }
+}
diff --git a/src/main/java/cn/lingsmc/lingshttputils/commands/WorkerOptionCommands.java b/src/main/java/cn/lingsmc/lingshttputils/commands/WorkerOptionCommands.java
new file mode 100644
index 0000000..72f04a4
--- /dev/null
+++ b/src/main/java/cn/lingsmc/lingshttputils/commands/WorkerOptionCommands.java
@@ -0,0 +1,51 @@
+package cn.lingsmc.lingshttputils.commands;
+
+import cn.lingsmc.lingshttputils.asyncworkers.WorkerOptions;
+import cn.lingsmc.lingshttputils.senders.MessageSender;
+import org.bukkit.ChatColor;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+import org.jetbrains.annotations.NotNull;
+
+import static cn.lingsmc.lingshttputils.commands.Commands.helpMessage;
+
+/**
+ * @author Crsuh2er0
+ * @date 2022/8/30
+ * @apiNote
+ */
+public class WorkerOptionCommands {
+ private WorkerOptionCommands() {
+ }
+
+ public static void workerOptionCommands(@NotNull CommandSender sender, String @NotNull [] args) {
+ if (args.length < 2) {
+ sender.sendMessage(helpMessage);
+ return;
+ }
+ if (!sender.hasPermission(Commands.permission)) {
+ sender.sendMessage(String.format("%s你没有执行此命令的权限.", ChatColor.RED));
+ return;
+ }
+ switch (args[1]) {
+ case "start":
+ if (!WorkerOptions.isStarted()) {
+ WorkerOptions.runWorkers();
+ MessageSender.sendMessage((Player) sender, String.format("%s正在启动Cycle Workers...", ChatColor.GREEN));
+ } else {
+ MessageSender.sendMessage((Player) sender, String.format("%sCycle Workers已启动!", ChatColor.RED));
+ }
+ return;
+ case "stop":
+ if (WorkerOptions.isStarted()) {
+ WorkerOptions.stopWorkers();
+ MessageSender.sendMessage((Player) sender, String.format("%s正在关闭Cycle Workers...", ChatColor.GREEN));
+ } else {
+ MessageSender.sendMessage((Player) sender, String.format("%sCycle Workers已关闭!", ChatColor.RED));
+ }
+ return;
+ default:
+ sender.sendMessage(helpMessage);
+ }
+ }
+}
diff --git a/src/main/java/cn/lingsmc/lingshttputils/placeholderapi/PlaceholderAPI.java b/src/main/java/cn/lingsmc/lingshttputils/placeholderapi/PlaceholderAPI.java
new file mode 100644
index 0000000..e82b419
--- /dev/null
+++ b/src/main/java/cn/lingsmc/lingshttputils/placeholderapi/PlaceholderAPI.java
@@ -0,0 +1,82 @@
+package cn.lingsmc.lingshttputils.placeholderapi;
+
+import cn.lingsmc.lingshttputils.LingsHTTPUtils;
+import cn.lingsmc.lingshttputils.requesters.HTTPRequester;
+import cn.lingsmc.lingshttputils.utils.JsonUtils;
+import me.clip.placeholderapi.expansion.PlaceholderExpansion;
+import org.bukkit.OfflinePlayer;
+import org.bukkit.configuration.file.FileConfiguration;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Objects;
+import java.util.Set;
+
+/**
+ * @author Crsuh2er0
+ * @date 2022/8/30
+ * @apiNote
+ */
+public class PlaceholderAPI extends PlaceholderExpansion {
+
+ private final LingsHTTPUtils plugin;
+ private final FileConfiguration config = LingsHTTPUtils.getInstance().getConfig();
+
+ public PlaceholderAPI(LingsHTTPUtils plugin) {
+ this.plugin = plugin;
+ }
+
+ @Override
+ public @NotNull String getAuthor() {
+ return LingsHTTPUtils.getInstance().getDescription().getAuthors().toString();
+ }
+
+ @Override
+ public @NotNull String getIdentifier() {
+ return "lhu";
+ }
+
+ @Override
+ public @NotNull String getVersion() {
+ return LingsHTTPUtils.getInstance().getDescription().getVersion();
+ }
+
+ @Override
+ public boolean persist() {
+ // 这是必要的,否则PAPI会在重载时卸载这个扩展
+ return true;
+
+ }
+
+ @Override
+ public String onRequest(OfflinePlayer p, @NotNull String params) {
+ Set modules = config.getKeys(false);
+ for (String module : modules) {
+ if (Objects.equals(params, config.getString(String.format("%s.apiname", module)))) {
+ if ("inTime".equals(config.getString(String.format("%s.reqMode", module)))) {
+ int reqTime = config.getInt(String.format("%s.reqTime", module));
+ String url = config.getString(String.format("%s.url", module));
+ String method;
+ try {
+ method = config.getString(String.format("%s.method", module));
+ } catch (Exception ignored) {
+ method = "GET";
+ }
+ String res = HTTPRequester.request(url, reqTime, method);
+ if (res == null) {
+ return "";
+ }
+ if ("json".equals(config.getString(String.format("%s.mode", module)))) {
+ String[] keys = config.getString(String.format("%s.key", module)).split("\\.");
+ res = JsonUtils.getValue(JsonUtils.parseStr(res), keys, 0);
+ }
+ return res;
+ } else {
+ // Cycle
+ return LingsHTTPUtils.getInstance().getHttpData().get(module);
+ }
+ }
+ }
+ // PAPI对扩展来说是未知的
+ return null;
+ }
+}
diff --git a/src/main/java/cn/lingsmc/lingshttputils/requesters/HTTPRequester.java b/src/main/java/cn/lingsmc/lingshttputils/requesters/HTTPRequester.java
new file mode 100644
index 0000000..bda5460
--- /dev/null
+++ b/src/main/java/cn/lingsmc/lingshttputils/requesters/HTTPRequester.java
@@ -0,0 +1,66 @@
+package cn.lingsmc.lingshttputils.requesters;
+
+import cn.lingsmc.lingshttputils.LingsHTTPUtils;
+
+import java.io.BufferedReader;
+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.Objects;
+
+/**
+ * @author Crsuh2er0
+ * @date 2022/8/30
+ * @apiNote
+ */
+public class HTTPRequester {
+ private HTTPRequester() {
+ }
+
+ public static String request(String httpUrl, int reqTime, String method) {
+ HttpURLConnection connection = null;
+ InputStream is = null;
+ BufferedReader br = null;
+ StringBuilder res = new StringBuilder();
+ try {
+ URL url = new URL(httpUrl);
+ connection = (HttpURLConnection) url.openConnection();
+ connection.setRequestMethod(method);
+ connection.setReadTimeout(reqTime);
+ connection.connect();
+ if (connection.getResponseCode() == 200) {
+ is = connection.getInputStream();
+ if (is != null) {
+ br = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8));
+ String tmp;
+ while ((tmp = br.readLine()) != null) {
+ res.append(tmp);
+ }
+ }
+ }
+ } catch (IOException e) {
+ LingsHTTPUtils.getInstance().getLogger().info("请求失败!");
+ return null;
+ } finally {
+ if (br != null) {
+ try {
+ br.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ if (is != null) {
+ try {
+ is.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ Objects.requireNonNull(connection).disconnect();
+ }
+ return res.toString();
+ }
+}
diff --git a/src/main/java/cn/lingsmc/lingshttputils/senders/MessageSender.java b/src/main/java/cn/lingsmc/lingshttputils/senders/MessageSender.java
new file mode 100644
index 0000000..8880d92
--- /dev/null
+++ b/src/main/java/cn/lingsmc/lingshttputils/senders/MessageSender.java
@@ -0,0 +1,21 @@
+package cn.lingsmc.lingshttputils.senders;
+
+import cn.lingsmc.lingshttputils.LingsHTTPUtils;
+import org.bukkit.ChatColor;
+import org.bukkit.entity.Player;
+
+/**
+ * @author Crsuh2er0
+ * @date 2022/8/30
+ * @apiNote
+ */
+public class MessageSender {
+ static final String MESSAGE_HEAD = String.format("%s[%s%s%s] %s", ChatColor.DARK_AQUA, ChatColor.AQUA, LingsHTTPUtils.getInstance().getName(), ChatColor.DARK_AQUA, ChatColor.RESET);
+
+ private MessageSender() {
+ }
+
+ public static void sendMessage(Player p, String message) {
+ p.sendMessage(String.format("%s%s", MESSAGE_HEAD, message));
+ }
+}
diff --git a/src/main/java/cn/lingsmc/lingshttputils/utils/JsonUtils.java b/src/main/java/cn/lingsmc/lingshttputils/utils/JsonUtils.java
new file mode 100644
index 0000000..d2296c1
--- /dev/null
+++ b/src/main/java/cn/lingsmc/lingshttputils/utils/JsonUtils.java
@@ -0,0 +1,32 @@
+package cn.lingsmc.lingshttputils.utils;
+
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author Crsuh2er0
+ * @date 2022/8/30
+ * @apiNote
+ */
+public class JsonUtils {
+ private JsonUtils() {
+ }
+
+ public static JsonObject parseStr(String str) {
+ return new JsonParser().parse(str).getAsJsonObject();
+ }
+
+ /**
+ * 递归深度读取json值
+ */
+ @Contract(pure = true)
+ public static String getValue(JsonObject json, String @NotNull [] keys, int depth) {
+ if (depth == keys.length - 1) {
+ return json.get(keys[keys.length - 1]).getAsString();
+ }
+ json = json.get(keys[depth++]).getAsJsonObject();
+ return getValue(json, keys, depth);
+ }
+}
diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml
new file mode 100644
index 0000000..8be092e
--- /dev/null
+++ b/src/main/resources/config.yml
@@ -0,0 +1,43 @@
+# LingsHTTPUtils 配置文件
+#
+# 每个模块名字随意
+#
+# mode
+# json 获取json格式的字符串并解析
+# string 直接获取文本
+#
+# key 当模式为json时要获取的值对应的键
+# 只在模式为json时可用
+#
+# apiname 比如你想要PAPI变量名为 %lhu_ab_cd% 那么apiname为"ab_cd"
+# 此插件的变量名头为lhu
+#
+# url 要请求的网页链接
+#
+# reqTime 请求超时时间(ms)
+#
+# refInterval 请求间隔时间
+#
+# method 请求方法 不指定则使用GET
+#
+# reqMode 请求方式
+# Cycle 循环请求
+# inTime 即时请求(注意可能卡住服务器)
+bilibili_followers:
+ apiname: "bilibili_followers"
+ url: "https://api.bilibili.com/x/relation/stat?vmid=359206390"
+ mode: "json"
+ method: "GET"
+ key: "data.follower"
+ reqTime: 1000
+ reqMode: "Cycle"
+ refInterval: 30000
+saying:
+ apiname: "saying"
+ url: "https://v1.hitokoto.cn/"
+ mode: "json"
+ method: "GET"
+ key: "hitokoto"
+ reqTime: 1000
+ reqMode: "Cycle"
+ refInterval: 15000
diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml
new file mode 100644
index 0000000..907fd36
--- /dev/null
+++ b/src/main/resources/plugin.yml
@@ -0,0 +1,19 @@
+name: LingsHTTPUtils
+version: '${project.version}'
+main: cn.lingsmc.lingshttputils.LingsHTTPUtils
+depend: [ PlaceholderAPI ]
+authors: [ Crsuh2er0 ]
+description: Connect website text with PAPI.
+api-version: 1.12
+loadbefore:
+ - LingsHTTPUtils
+commands:
+ lingshttputils:
+ description: LingsHTTPUtils插件指令
+ aliases:
+ - lhu
+ usage: |
+ /lhu help
+permissions:
+ lingshttputils.admin:
+ description: LingsHTTPUtils插件管理权限
\ No newline at end of file