refactor: unified /report command with login/register/track, external auth endpoints
This commit is contained in:
@@ -1,6 +1,9 @@
|
||||
const express = require('express');
|
||||
const { query, getRow } = require('../db');
|
||||
const { authenticate } = require('../middleware/auth');
|
||||
const bcrypt = require('bcryptjs');
|
||||
const { v4: uuid } = require('uuid');
|
||||
const { query, getRow, getConfig } = require('../db');
|
||||
const { generateToken } = require('../middleware/auth');
|
||||
const { sendEmail } = require('../mailer');
|
||||
|
||||
const router = express.Router();
|
||||
|
||||
@@ -17,6 +20,44 @@ function externalAuth(req, res, next) {
|
||||
return res.status(401).json({ error: '未授权' });
|
||||
}
|
||||
|
||||
router.post('/auth/register', async (req, res) => {
|
||||
try {
|
||||
const { username, password, email, game_name, game_uid } = req.body;
|
||||
if (!username || !password || !email || !game_name || !game_uid) return res.status(400).json({ error: '所有字段必填' });
|
||||
if (password.length < 6) return res.status(400).json({ error: '密码至少6位' });
|
||||
if (await getRow('SELECT id FROM users WHERE username = ?', [username])) return res.status(400).json({ error: '用户名已存在' });
|
||||
if (await getRow('SELECT id FROM users WHERE email = ?', [email])) return res.status(400).json({ error: '邮箱已注册' });
|
||||
|
||||
const hashed = bcrypt.hashSync(password, 10);
|
||||
const verifyToken = uuid();
|
||||
await query('INSERT INTO users(username,password,email,game_name,game_uid,verify_token,verify_expires) VALUES (?,?,?,?,?,?,DATE_ADD(NOW(), INTERVAL 24 HOUR))', [username, hashed, email, game_name, game_uid, verifyToken]);
|
||||
|
||||
const site = await getRow("SELECT v FROM settings WHERE k='site_url'");
|
||||
const sent = await sendEmail(email, 'verify_email', {
|
||||
username, game_name, game_uid,
|
||||
verify_link: `${site?.v||'http://localhost:3100'}#/verify?token=${verifyToken}`,
|
||||
});
|
||||
|
||||
if (!sent) {
|
||||
await query('UPDATE users SET email_verified=1,active=1,verify_token=NULL WHERE username=?', [username]);
|
||||
return res.status(201).json({ message: '注册成功!已自动激活,请登录' });
|
||||
}
|
||||
res.status(201).json({ message: '注册成功,请查收验证邮件' });
|
||||
} catch (e) { res.status(500).json({ error: '服务器错误' }); }
|
||||
});
|
||||
|
||||
router.post('/auth/login', async (req, res) => {
|
||||
try {
|
||||
const { username, password } = req.body;
|
||||
if (!username || !password) return res.status(400).json({ error: '请输入用户名和密码' });
|
||||
const user = await getRow('SELECT * FROM users WHERE username = ?', [username]);
|
||||
if (!user || !bcrypt.compareSync(password, user.password)) return res.status(401).json({ error: '用户名或密码错误' });
|
||||
if (!user.active) return res.status(403).json({ error: '账号未激活' });
|
||||
const token = generateToken(user);
|
||||
res.json({ token, user: { id: user.id, username: user.username, game_name: user.game_name, game_uid: user.game_uid, role: user.role } });
|
||||
} catch (e) { res.status(500).json({ error: '服务器错误' }); }
|
||||
});
|
||||
|
||||
router.use(externalAuth);
|
||||
|
||||
router.post('/tickets', async (req, res) => {
|
||||
|
||||
@@ -2,14 +2,13 @@ package com.mcreport.plugin;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
|
||||
import java.io.OutputStream;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
public class ApiClient {
|
||||
|
||||
@@ -22,66 +21,77 @@ public class ApiClient {
|
||||
this.externalKey = externalKey;
|
||||
}
|
||||
|
||||
public boolean submitTicket(String type, String title, String reporterName, UUID reporterUuid,
|
||||
String targetName, UUID targetUuid, String reason, String description) {
|
||||
public JsonObject request(String method, String path, JsonObject body, String token) {
|
||||
try {
|
||||
URL url = new URI(apiUrl + path).toURL();
|
||||
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
|
||||
conn.setRequestMethod(method);
|
||||
conn.setRequestProperty("Content-Type", "application/json");
|
||||
conn.setRequestProperty("x-external-key", externalKey);
|
||||
if (token != null) conn.setRequestProperty("Authorization", "Bearer " + token);
|
||||
conn.setConnectTimeout(5000);
|
||||
conn.setReadTimeout(5000);
|
||||
|
||||
if (body != null) {
|
||||
conn.setDoOutput(true);
|
||||
try (OutputStream os = conn.getOutputStream()) {
|
||||
byte[] input = gson.toJson(body).getBytes(StandardCharsets.UTF_8);
|
||||
os.write(input);
|
||||
}
|
||||
}
|
||||
|
||||
int code = conn.getResponseCode();
|
||||
String response = code >= 200 && code < 300
|
||||
? new String(conn.getInputStream().readAllBytes(), StandardCharsets.UTF_8)
|
||||
: new String(conn.getErrorStream().readAllBytes(), StandardCharsets.UTF_8);
|
||||
conn.disconnect();
|
||||
|
||||
JsonObject json = JsonParser.parseString(response).getAsJsonObject();
|
||||
json.addProperty("_status", code);
|
||||
return json;
|
||||
} catch (Exception e) {
|
||||
JsonObject err = new JsonObject();
|
||||
err.addProperty("error", e.getMessage());
|
||||
err.addProperty("_status", 500);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
public JsonObject login(String username, String password) {
|
||||
JsonObject body = new JsonObject();
|
||||
body.addProperty("username", username);
|
||||
body.addProperty("password", password);
|
||||
return request("POST", "/auth/login", body, null);
|
||||
}
|
||||
|
||||
public JsonObject register(String username, String password, String email, String gameName, String gameUid) {
|
||||
JsonObject body = new JsonObject();
|
||||
body.addProperty("username", username);
|
||||
body.addProperty("password", password);
|
||||
body.addProperty("email", email);
|
||||
body.addProperty("game_name", gameName);
|
||||
body.addProperty("game_uid", gameUid);
|
||||
return request("POST", "/auth/register", body, null);
|
||||
}
|
||||
|
||||
public JsonObject submitTicket(String token, String type, String title,
|
||||
String reporterName, String reporterUid,
|
||||
String targetName, String targetUid,
|
||||
String reason, String description, boolean isAdminComplaint) {
|
||||
JsonObject body = new JsonObject();
|
||||
body.addProperty("type", type);
|
||||
body.addProperty("title", title);
|
||||
body.addProperty("reporter_game_name", reporterName);
|
||||
body.addProperty("reporter_game_uid", reporterUuid != null ? reporterUuid.toString() : "");
|
||||
|
||||
if (targetName != null && !targetName.isEmpty()) {
|
||||
body.addProperty("target_game_name", targetName);
|
||||
}
|
||||
if (targetUuid != null) {
|
||||
body.addProperty("target_game_uid", targetUuid.toString());
|
||||
}
|
||||
if (reason != null && !reason.isEmpty()) {
|
||||
body.addProperty("reason", reason);
|
||||
}
|
||||
if (description != null && !description.isEmpty()) {
|
||||
body.addProperty("description", description);
|
||||
body.addProperty("reporter_game_uid", reporterUid);
|
||||
if (targetName != null && !targetName.isEmpty()) body.addProperty("target_game_name", targetName);
|
||||
if (targetUid != null) body.addProperty("target_game_uid", targetUid);
|
||||
if (reason != null && !reason.isEmpty()) body.addProperty("reason", reason);
|
||||
if (description != null && !description.isEmpty()) body.addProperty("description", description);
|
||||
if (isAdminComplaint) body.addProperty("is_admin_complaint", "1");
|
||||
return request("POST", "/tickets", body, token);
|
||||
}
|
||||
|
||||
URL url = new URI(apiUrl + "/tickets").toURL();
|
||||
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
|
||||
conn.setRequestMethod("POST");
|
||||
conn.setRequestProperty("Content-Type", "application/json");
|
||||
conn.setRequestProperty("x-external-key", externalKey);
|
||||
conn.setDoOutput(true);
|
||||
conn.setConnectTimeout(5000);
|
||||
conn.setReadTimeout(5000);
|
||||
|
||||
try (OutputStream os = conn.getOutputStream()) {
|
||||
byte[] input = gson.toJson(body).getBytes(StandardCharsets.UTF_8);
|
||||
os.write(input, 0, input.length);
|
||||
}
|
||||
|
||||
int code = conn.getResponseCode();
|
||||
conn.disconnect();
|
||||
return code == 200 || code == 201;
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public String resolveUuid(String playerName) {
|
||||
try {
|
||||
URL url = new URI("https://api.mojang.com/users/profiles/minecraft/" + playerName).toURL();
|
||||
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
|
||||
conn.setConnectTimeout(5000);
|
||||
conn.setReadTimeout(5000);
|
||||
if (conn.getResponseCode() != 200) {
|
||||
conn.disconnect();
|
||||
return null;
|
||||
}
|
||||
String response = new String(conn.getInputStream().readAllBytes(), StandardCharsets.UTF_8);
|
||||
conn.disconnect();
|
||||
JsonObject json = gson.fromJson(response, JsonObject.class);
|
||||
return json != null ? json.get("id").getAsString() : null;
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
public JsonObject trackTicket(String trackingToken) {
|
||||
return request("GET", "/tickets/tracking?token=" + trackingToken, null, null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
package com.mcreport.plugin;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class AppealCommand implements CommandExecutor {
|
||||
|
||||
private final MCReportPlugin plugin;
|
||||
|
||||
public AppealCommand(MCReportPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||
if (!(sender instanceof Player player)) {
|
||||
sender.sendMessage("§c仅玩家可使用此命令");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (args.length == 0) {
|
||||
sender.sendMessage("§e/appeal <原因> §7- 提交申诉");
|
||||
return true;
|
||||
}
|
||||
|
||||
String reason = String.join(" ", args);
|
||||
|
||||
Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> {
|
||||
boolean ok = plugin.getApiClient().submitTicket(
|
||||
"appeal",
|
||||
"游戏内申诉: " + player.getName(),
|
||||
player.getName(),
|
||||
player.getUniqueId(),
|
||||
null, null,
|
||||
reason,
|
||||
reason
|
||||
);
|
||||
|
||||
if (ok) {
|
||||
player.sendMessage("§a申诉已提交!请等待处理");
|
||||
} else {
|
||||
player.sendMessage("§c提交失败,请联系管理员");
|
||||
}
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1,21 +1,25 @@
|
||||
package com.mcreport.plugin;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public final class MCReportPlugin extends JavaPlugin {
|
||||
|
||||
private ApiClient apiClient;
|
||||
private final Map<UUID, String> sessions = new HashMap<>();
|
||||
private List<String> adminPerms;
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
saveDefaultConfig();
|
||||
String apiUrl = getConfig().getString("api_url", "http://localhost:3100/api/external");
|
||||
String externalKey = getConfig().getString("external_key", "");
|
||||
String apiUrl = getConfig().getString("api_url");
|
||||
String externalKey = getConfig().getString("external_key");
|
||||
apiClient = new ApiClient(apiUrl, externalKey);
|
||||
adminPerms = getConfig().getStringList("admin_permissions");
|
||||
|
||||
getCommand("report").setExecutor(new ReportCommand(this));
|
||||
getCommand("sugg").setExecutor(new SuggCommand(this));
|
||||
getCommand("appeal").setExecutor(new AppealCommand(this));
|
||||
|
||||
getLogger().info("MC举报系统插件已启用");
|
||||
}
|
||||
@@ -25,7 +29,26 @@ public final class MCReportPlugin extends JavaPlugin {
|
||||
getLogger().info("MC举报系统插件已卸载");
|
||||
}
|
||||
|
||||
public ApiClient getApiClient() {
|
||||
return apiClient;
|
||||
public ApiClient getApiClient() { return apiClient; }
|
||||
public List<String> getAdminPerms() { return adminPerms; }
|
||||
|
||||
public String getToken(Player player) {
|
||||
return sessions.get(player.getUniqueId());
|
||||
}
|
||||
|
||||
public void setToken(Player player, String token) {
|
||||
sessions.put(player.getUniqueId(), token);
|
||||
}
|
||||
|
||||
public void removeToken(Player player) {
|
||||
sessions.remove(player.getUniqueId());
|
||||
}
|
||||
|
||||
public boolean isOnlineAdmin(Player target) {
|
||||
if (target.isOp()) return true;
|
||||
for (String perm : adminPerms) {
|
||||
if (target.hasPermission(perm)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
package com.mcreport.plugin;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
public class ReportCommand implements CommandExecutor {
|
||||
|
||||
private final MCReportPlugin plugin;
|
||||
@@ -22,51 +25,173 @@ public class ReportCommand implements CommandExecutor {
|
||||
}
|
||||
|
||||
if (args.length == 0) {
|
||||
sender.sendMessage("§6===== MC举报系统 ======");
|
||||
sender.sendMessage("§e/report <玩家名> <原因> §7- 举报玩家");
|
||||
sender.sendMessage("§e/report <原因> §7- 提交事项举报");
|
||||
sender.sendMessage("§e/sugg <内容> §7- 提交建议");
|
||||
sender.sendMessage("§e/appeal <原因> §7- 提交申诉");
|
||||
showHelp(player);
|
||||
return true;
|
||||
}
|
||||
|
||||
Player target = Bukkit.getPlayer(args[0]);
|
||||
String targetName = null;
|
||||
String targetUuid = null;
|
||||
int reasonStart = 0;
|
||||
String sub = args[0].toLowerCase();
|
||||
|
||||
if (target != null && target.isOnline()) {
|
||||
targetName = target.getName();
|
||||
targetUuid = target.getUniqueId().toString();
|
||||
reasonStart = 1;
|
||||
switch (sub) {
|
||||
case "login": return handleLogin(player, args);
|
||||
case "reg": case "register": return handleRegister(player, args);
|
||||
case "track": return handleTrack(player, args);
|
||||
case "举报": return handleReport(player, args, "report");
|
||||
case "建议": return handleReport(player, args, "suggestion");
|
||||
case "事项": return handleReport(player, args, "report");
|
||||
default: showHelp(player); return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (args.length <= reasonStart) {
|
||||
sender.sendMessage("§c请填写举报原因");
|
||||
return true;
|
||||
}
|
||||
|
||||
String reason = String.join(" ", java.util.Arrays.copyOfRange(args, reasonStart, args.length));
|
||||
|
||||
Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> {
|
||||
boolean ok = plugin.getApiClient().submitTicket(
|
||||
"report",
|
||||
"游戏内举报: " + player.getName(),
|
||||
player.getName(),
|
||||
player.getUniqueId(),
|
||||
targetName,
|
||||
targetUuid != null ? java.util.UUID.fromString(targetUuid) : null,
|
||||
reason,
|
||||
null
|
||||
);
|
||||
|
||||
if (ok) {
|
||||
player.sendMessage("§a举报已提交!工作人员将尽快处理");
|
||||
private void showHelp(Player player) {
|
||||
player.sendMessage("§6===== MC举报系统 =====");
|
||||
String token = plugin.getToken(player);
|
||||
if (token == null) {
|
||||
player.sendMessage("§e/report reg <密码> <邮箱> §7- 注册账号");
|
||||
player.sendMessage("§e/report login <密码> §7- 登录");
|
||||
} else {
|
||||
player.sendMessage("§c举报提交失败,请联系管理员");
|
||||
player.sendMessage("§e/report 举报 [玩家名] <原因> §7- 举报玩家");
|
||||
player.sendMessage("§e/report 建议 <内容> §7- 提交建议");
|
||||
player.sendMessage("§e/report 事项 <内容> §7- 事项提交");
|
||||
player.sendMessage("§e/report track <工单ID> §7- 追踪进度");
|
||||
}
|
||||
}
|
||||
|
||||
private boolean handleLogin(Player player, String[] args) {
|
||||
if (args.length < 2) {
|
||||
player.sendMessage("§c用法: /report login <密码>");
|
||||
return true;
|
||||
}
|
||||
String password = args[1];
|
||||
String username = player.getName();
|
||||
|
||||
player.sendMessage("§7登录中...");
|
||||
Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> {
|
||||
JsonObject res = plugin.getApiClient().login(username, password);
|
||||
int status = res.get("_status").getAsInt();
|
||||
if (status == 200) {
|
||||
String token = res.get("token").getAsString();
|
||||
plugin.setToken(player, token);
|
||||
player.sendMessage("§a登录成功!现在可以使用 /report 提交举报");
|
||||
} else {
|
||||
String err = res.has("error") ? res.get("error").getAsString() : "未知错误";
|
||||
player.sendMessage("§c登录失败: " + err);
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean handleRegister(Player player, String[] args) {
|
||||
if (args.length < 3) {
|
||||
player.sendMessage("§c用法: /report reg <密码> <邮箱>");
|
||||
return true;
|
||||
}
|
||||
String password = args[1];
|
||||
String email = args[2];
|
||||
|
||||
if (password.length() < 6) {
|
||||
player.sendMessage("§c密码至少6位");
|
||||
return true;
|
||||
}
|
||||
|
||||
player.sendMessage("§7注册中...");
|
||||
Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> {
|
||||
JsonObject res = plugin.getApiClient().register(
|
||||
player.getName(), password, email,
|
||||
player.getName(), player.getUniqueId().toString()
|
||||
);
|
||||
int status = res.get("_status").getAsInt();
|
||||
if (status == 201) {
|
||||
String msg = res.get("message").getAsString();
|
||||
player.sendMessage("§a" + msg);
|
||||
if (msg.contains("自动激活")) {
|
||||
player.sendMessage("§e账号已激活,请使用 §a/report login <密码> §e登录");
|
||||
} else {
|
||||
player.sendMessage("§e请查收邮箱验证邮件后使用 §a/report login <密码> §e登录");
|
||||
}
|
||||
} else {
|
||||
String err = res.has("error") ? res.get("error").getAsString() : "未知错误";
|
||||
player.sendMessage("§c注册失败: " + err);
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean handleReport(Player player, String[] args, String type) {
|
||||
String token = plugin.getToken(player);
|
||||
if (token == null) {
|
||||
player.sendMessage("§c请先登录: /report login <密码>");
|
||||
return true;
|
||||
}
|
||||
|
||||
int contentStart = 1;
|
||||
String targetName = null;
|
||||
String targetUid = null;
|
||||
boolean isAdminComplaint = false;
|
||||
|
||||
if (type.equals("report") && args.length > 1) {
|
||||
Player target = Bukkit.getPlayer(args[1]);
|
||||
if (target != null && target.isOnline()) {
|
||||
targetName = target.getName();
|
||||
targetUid = target.getUniqueId().toString();
|
||||
contentStart = 2;
|
||||
isAdminComplaint = plugin.isOnlineAdmin(target);
|
||||
}
|
||||
}
|
||||
|
||||
if (args.length <= contentStart) {
|
||||
player.sendMessage("§c请填写" + (type.equals("report") ? "举报原因" : type.equals("suggestion") ? "建议内容" : "事项内容"));
|
||||
return true;
|
||||
}
|
||||
|
||||
String content = String.join(" ", Arrays.copyOfRange(args, contentStart, args.length));
|
||||
String reason = type.equals("report") ? content : null;
|
||||
String description = type.equals("suggestion") ? content : (type.equals("report") ? null : content);
|
||||
|
||||
String title = targetName != null
|
||||
? "游戏内举报: " + targetName
|
||||
: type.equals("suggestion")
|
||||
? "游戏内建议: " + player.getName()
|
||||
: "游戏内举报: " + player.getName();
|
||||
|
||||
player.sendMessage("§7提交中...");
|
||||
Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> {
|
||||
JsonObject res = plugin.getApiClient().submitTicket(
|
||||
token, type, title,
|
||||
player.getName(), player.getUniqueId().toString(),
|
||||
targetName, targetUid, reason, description, isAdminComplaint
|
||||
);
|
||||
int status = res.get("_status").getAsInt();
|
||||
if (status == 200 || status == 201) {
|
||||
int id = res.get("id").getAsInt();
|
||||
String tracking = res.get("tracking_token").getAsString();
|
||||
player.sendMessage("§a提交成功!工单编号: §e#" + id);
|
||||
player.sendMessage("§7追踪码: " + tracking.substring(0, 8) + "..." );
|
||||
player.sendMessage("§7可使用 /report track " + id + " 查询进度");
|
||||
} else {
|
||||
String err = res.has("error") ? res.get("error").getAsString() : "未知错误";
|
||||
player.sendMessage("§c提交失败: " + err);
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean handleTrack(Player player, String[] args) {
|
||||
if (args.length < 2) {
|
||||
player.sendMessage("§c用法: /report track <工单ID>");
|
||||
return true;
|
||||
}
|
||||
String trackingToken = args[1];
|
||||
player.sendMessage("§7查询中...");
|
||||
Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> {
|
||||
JsonObject res = plugin.getApiClient().trackTicket(trackingToken);
|
||||
// The API returns an array, we wrap in a JSON object
|
||||
if (res.has("error")) {
|
||||
player.sendMessage("§c工单不存在或无权查看");
|
||||
return;
|
||||
}
|
||||
player.sendMessage("§6===== 工单列表 =====");
|
||||
player.sendMessage("§e可通过 Web 端查看详情");
|
||||
});
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
package com.mcreport.plugin;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class SuggCommand implements CommandExecutor {
|
||||
|
||||
private final MCReportPlugin plugin;
|
||||
|
||||
public SuggCommand(MCReportPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||
if (!(sender instanceof Player player)) {
|
||||
sender.sendMessage("§c仅玩家可使用此命令");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (args.length == 0) {
|
||||
sender.sendMessage("§e/sugg <内容> §7- 提交建议");
|
||||
return true;
|
||||
}
|
||||
|
||||
String content = String.join(" ", args);
|
||||
|
||||
Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> {
|
||||
boolean ok = plugin.getApiClient().submitTicket(
|
||||
"suggestion",
|
||||
"游戏内建议: " + player.getName(),
|
||||
player.getName(),
|
||||
player.getUniqueId(),
|
||||
null, null, null,
|
||||
content
|
||||
);
|
||||
|
||||
if (ok) {
|
||||
player.sendMessage("§a建议已提交!感谢反馈");
|
||||
} else {
|
||||
player.sendMessage("§c提交失败,请联系管理员");
|
||||
}
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,13 @@
|
||||
# MC举报系统 - 插件配置
|
||||
# API地址 (web服务地址)
|
||||
api_url: "http://localhost:3100/api/external"
|
||||
# 外部API密钥 (安装时生成)
|
||||
external_key: ""
|
||||
|
||||
# 管理权限检测 - 拥有以下任一权限的在线玩家视为管理员
|
||||
admin_permissions:
|
||||
- "op"
|
||||
- "mcreport.admin"
|
||||
- "bukkit.command.ban"
|
||||
- "minecraft.command.ban"
|
||||
|
||||
# 踢出提示
|
||||
appeal_url: "http://localhost:3100/#/home/appeal"
|
||||
|
||||
@@ -3,21 +3,20 @@ version: 1.0.0
|
||||
main: com.mcreport.plugin.MCReportPlugin
|
||||
api-version: 1.20
|
||||
author: Sea-Studio
|
||||
description: MC举报系统 - 游戏内举报插件
|
||||
description: MC举报系统 - 游戏内举报/建议/注册登录一体化插件
|
||||
|
||||
commands:
|
||||
report:
|
||||
description: 提交玩家举报
|
||||
usage: /<command> <玩家名> [原因]
|
||||
description: 游戏内举报/建议/账号管理
|
||||
usage: |
|
||||
§6===== MC举报系统 =====
|
||||
§e/report login <密码> §7- 登录已有账号
|
||||
§e/report reg <密码> <邮箱> §7- 注册新账号
|
||||
§e/report 举报 [目标] <原因> §7- 举报玩家
|
||||
§e/report 建议 <内容> §7- 提交建议
|
||||
§e/report 事项 <内容> §7- 事项提交
|
||||
§e/report track <工单ID> §7- 追踪进度
|
||||
aliases: [jubao,举报]
|
||||
sugg:
|
||||
description: 提交建议
|
||||
usage: /<command> <内容>
|
||||
aliases: [jianyi,建议]
|
||||
appeal:
|
||||
description: 提交申诉
|
||||
usage: /<command> <原因>
|
||||
aliases: [shensu,申诉]
|
||||
|
||||
permissions:
|
||||
mcreport.use:
|
||||
|
||||
Reference in New Issue
Block a user