- mc-report-plugin removed from git tracking (kept locally), gitignored; plugin code no longer distributed (old x-external-key auth, outdated) - docs/PLUGIN-GUIDE.md: Java plugin integration guide using new ID+Secret -> SESSION auth (session mgmt, submit ticket, track, bans) - README: updated external API table (SESSION), dynamic sources, removed obsolete plugin commands/tech row, new dir structure, doc links - INSTALL: drop restart requirement, add upgrade-migration/log/sources sections, license section - LICENSE: GNU AGPL v3 full text - verified: 24 checks (git tracking, docs consistency, license integrity)
6.0 KiB
6.0 KiB
MC 插件对接指南(外部 API)
本文面向 Bukkit/Paper/Spigot 插件开发者,演示如何用 Java 对接 MC Report 外部 API(提交举报、同步封禁、查询进度)。完整接口定义见 EXTERNAL-API.md。
仓库不再内置插件代码 —— 按本指南即可自行实现;凭据(ID+Secret)在站点后台「外部API」页创建。
一、鉴权流程(Java 实现)
外部 API 用 ID + Secret 换取 SESSION,之后所有请求带 Authorization: Bearer <SESSION>。
public class McReportApi {
private final String baseUrl; // 如 https://mc.example.com/api/external
private final String clientId; // 后台创建: 16 位数字
private final String clientSecret; // 后台创建: 32 位随机串
private String sessionToken;
private long sessionExpiresAt; // 到期时间戳(ms)
public McReportApi(String baseUrl, String clientId, String clientSecret) {
this.baseUrl = baseUrl;
this.clientId = clientId;
this.clientSecret = clientSecret;
}
/** 获取有效 SESSION, 过期则自动换新 */
public synchronized String session() throws Exception {
if (sessionToken != null && System.currentTimeMillis() < sessionExpiresAt) {
return sessionToken;
}
JSONObject body = new JSONObject();
HttpURLConnection conn = open("POST", "/auth/session", null);
conn.setRequestProperty("x-api-client-id", clientId);
conn.setRequestProperty("x-api-secret", clientSecret);
conn.setDoOutput(true);
conn.getOutputStream().write(body.toString().getBytes(StandardCharsets.UTF_8));
JSONObject resp = readJson(conn);
sessionToken = resp.getString("session_token");
sessionExpiresAt = System.currentTimeMillis() + resp.getLong("expires_in") * 1000L - 60_000L; // 提前1分钟过期
return sessionToken;
}
private HttpURLConnection open(String method, String path, String token) throws Exception {
HttpURLConnection conn = (HttpURLConnection) new URL(baseUrl + path).openConnection();
conn.setRequestMethod(method);
conn.setConnectTimeout(5000);
conn.setReadTimeout(10000);
conn.setRequestProperty("Content-Type", "application/json");
conn.setRequestProperty("User-Agent", "MCReportPlugin/1.0");
if (token != null) conn.setRequestProperty("Authorization", "Bearer " + token);
return conn;
}
private JSONObject readJson(HttpURLConnection conn) throws Exception {
int code = conn.getResponseCode();
InputStream in = code >= 200 && code < 300 ? conn.getInputStream() : conn.getErrorStream();
String text = new String(in.readAllBytes(), StandardCharsets.UTF_8);
JSONObject json = new JSONObject(text);
if (code >= 400) throw new RuntimeException(json.optString("error", "HTTP " + code));
return json;
}
}
二、提交举报工单
/** 玩家在游戏内执行 /report 命令时调用 */
public JSONObject submitReport(String reporterName, String targetName, String reason,
String serverName, String description) throws Exception {
String token = session();
JSONObject body = new JSONObject();
body.put("type", "report");
body.put("title", "游戏内举报: " + targetName);
body.put("reporter_game_name", reporterName);
body.put("target_game_name", targetName);
body.put("reason", reason);
body.put("description", description);
body.put("server", serverName); // 子服别名或「分组/子服」
HttpURLConnection conn = open("POST", "/tickets", token);
conn.setDoOutput(true);
conn.getOutputStream().write(body.toString().getBytes(StandardCharsets.UTF_8));
JSONObject resp = readJson(conn);
// resp: {"id": 123, "tracking_token": "..."}
return resp;
}
返回的 tracking_token 请保存(例如写进玩家持久数据),玩家可用它查询处理进度:
public JSONObject trackTicket(String trackingToken) throws Exception {
return readJson(open("GET", "/tickets/track?token=" + URLEncoder.encode(trackingToken, "UTF-8"), session()));
}
三、拉取/同步封禁
/** 定时任务: 每 5 分钟同步一次本服生效封禁 */
public JSONArray fetchActiveBans(String serverName) throws Exception {
String token = session();
String path = "/bans?status=active&limit=500"
+ (serverName != null && !serverName.isEmpty()
? "&server=" + URLEncoder.encode(serverName, "UTF-8") : "");
return readJson(open("GET", path, token)).getJSONArray("data");
}
/** 服务器内封禁玩家后同步到系统 */
public JSONObject createBan(String playerName, String reason, String type,
String duration, String serverName) throws Exception {
JSONObject body = new JSONObject();
body.put("player_name", playerName);
body.put("reason", reason);
body.put("type", type); // ban / mute / warn
body.put("duration", duration); // 如 "7d", 空=永久
body.put("server", serverName);
return readJson(open("POST", "/bans", session())); // 需带 body
}
注意:
POST /bans需设置setDoOutput(true)并写入 body(与 submitReport 相同写法)。
四、配置
plugins/<你的插件>/config.yml:
# MC Report 外部 API 配置
api_url: "https://mc.example.com/api/external"
client_id: "1829473056482917" # 后台「外部API」创建
client_secret: "a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6"
server_name: "survival" # 本服别名(后台服务器管理配置)
常见问题
| 问题 | 处理 |
|---|---|
401 |
ID/Secret 错误或客户端被停用;检查后台「外部API」 |
401 SESSION 无效或已过期 |
重新调用 /auth/session 换取(示例代码已自动处理) |
400 待处理工单已达上限 |
同一玩家待处理工单最多 5 个 |
| 换服/改名 | 用 server 参数按子服隔离数据;玩家身份以 game_name 为准 |