koishi-plugin-bind-bot 2.0.0 → 2.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +35 -0
- package/lib/handlers/base.handler.d.ts +15 -1
- package/lib/handlers/mcid.handler.d.ts +3 -39
- package/lib/handlers/mcid.handler.js +135 -139
- package/lib/handlers/whitelist.handler.d.ts +0 -4
- package/lib/handlers/whitelist.handler.js +3 -32
- package/lib/index.js +24 -155
- package/lib/utils/error-utils.d.ts +30 -0
- package/lib/utils/error-utils.js +111 -0
- package/lib/utils/helpers.d.ts +15 -0
- package/lib/utils/helpers.js +46 -0
- package/package.json +2 -2
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.WhitelistHandler = void 0;
|
|
4
4
|
const koishi_1 = require("koishi");
|
|
5
5
|
const base_handler_1 = require("./base.handler");
|
|
6
|
+
const helpers_1 = require("../utils/helpers");
|
|
6
7
|
/**
|
|
7
8
|
* 白名单命令处理器
|
|
8
9
|
* 处理所有 mcid.whitelist 子命令
|
|
@@ -756,38 +757,8 @@ class WhitelistHandler extends base_handler_1.BaseHandler {
|
|
|
756
757
|
if (b.includes(a)) {
|
|
757
758
|
return a.length / b.length;
|
|
758
759
|
}
|
|
759
|
-
//
|
|
760
|
-
|
|
761
|
-
const editDistance = this.levenshteinDistance(a, b);
|
|
762
|
-
return 1 - (editDistance / maxLength);
|
|
763
|
-
}
|
|
764
|
-
/**
|
|
765
|
-
* 私有辅助方法:计算Levenshtein距离
|
|
766
|
-
*/
|
|
767
|
-
levenshteinDistance(a, b) {
|
|
768
|
-
const matrix = [];
|
|
769
|
-
// 初始化矩阵
|
|
770
|
-
for (let i = 0; i <= b.length; i++) {
|
|
771
|
-
matrix[i] = [i];
|
|
772
|
-
}
|
|
773
|
-
for (let j = 0; j <= a.length; j++) {
|
|
774
|
-
matrix[0][j] = j;
|
|
775
|
-
}
|
|
776
|
-
// 填充矩阵
|
|
777
|
-
for (let i = 1; i <= b.length; i++) {
|
|
778
|
-
for (let j = 1; j <= a.length; j++) {
|
|
779
|
-
if (b.charAt(i - 1) === a.charAt(j - 1)) {
|
|
780
|
-
matrix[i][j] = matrix[i - 1][j - 1];
|
|
781
|
-
}
|
|
782
|
-
else {
|
|
783
|
-
matrix[i][j] = Math.min(matrix[i - 1][j - 1] + 1, // 替换
|
|
784
|
-
matrix[i][j - 1] + 1, // 插入
|
|
785
|
-
matrix[i - 1][j] + 1 // 删除
|
|
786
|
-
);
|
|
787
|
-
}
|
|
788
|
-
}
|
|
789
|
-
}
|
|
790
|
-
return matrix[b.length][a.length];
|
|
760
|
+
// 否则使用工具函数计算Levenshtein距离的相似度
|
|
761
|
+
return (0, helpers_1.calculateSimilarity)(a, b);
|
|
791
762
|
}
|
|
792
763
|
/**
|
|
793
764
|
* 私有辅助方法:检查用户是否在特定服务器的白名单中
|
package/lib/index.js
CHANGED
|
@@ -12,6 +12,8 @@ const export_utils_1 = require("./export-utils");
|
|
|
12
12
|
const logger_1 = require("./utils/logger");
|
|
13
13
|
const rcon_manager_1 = require("./managers/rcon-manager");
|
|
14
14
|
const rate_limiter_1 = require("./utils/rate-limiter");
|
|
15
|
+
const helpers_1 = require("./utils/helpers");
|
|
16
|
+
const error_utils_1 = require("./utils/error-utils");
|
|
15
17
|
const mcidbind_repository_1 = require("./repositories/mcidbind.repository");
|
|
16
18
|
const schedule_mute_repository_1 = require("./repositories/schedule-mute.repository");
|
|
17
19
|
const handlers_1 = require("./handlers");
|
|
@@ -911,88 +913,6 @@ function apply(ctx, config) {
|
|
|
911
913
|
return extractedId;
|
|
912
914
|
};
|
|
913
915
|
// 获取用户友好的错误信息
|
|
914
|
-
const getFriendlyErrorMessage = (error) => {
|
|
915
|
-
const errorMsg = error instanceof Error ? error.message : error;
|
|
916
|
-
// 拆分错误信息
|
|
917
|
-
const userError = getUserFacingErrorMessage(errorMsg);
|
|
918
|
-
// 将警告级别错误标记出来
|
|
919
|
-
if (isWarningError(userError)) {
|
|
920
|
-
return `⚠️ ${userError}`;
|
|
921
|
-
}
|
|
922
|
-
// 将严重错误标记出来
|
|
923
|
-
if (isCriticalError(userError)) {
|
|
924
|
-
return `❌ ${userError}`;
|
|
925
|
-
}
|
|
926
|
-
return userError;
|
|
927
|
-
};
|
|
928
|
-
// 提取用户友好的错误信息
|
|
929
|
-
const getUserFacingErrorMessage = (errorMsg) => {
|
|
930
|
-
// Mojang API相关错误
|
|
931
|
-
if (errorMsg.includes('ECONNABORTED') || errorMsg.includes('timeout')) {
|
|
932
|
-
return '无法连接到Mojang服务器,请稍后再试';
|
|
933
|
-
}
|
|
934
|
-
if (errorMsg.includes('404')) {
|
|
935
|
-
return '该Minecraft用户名不存在';
|
|
936
|
-
}
|
|
937
|
-
if (errorMsg.includes('network') || errorMsg.includes('connect')) {
|
|
938
|
-
return '网络连接异常,请稍后再试';
|
|
939
|
-
}
|
|
940
|
-
// 数据库相关错误
|
|
941
|
-
if (errorMsg.includes('unique') || errorMsg.includes('duplicate')) {
|
|
942
|
-
return '该Minecraft用户名已被其他用户绑定';
|
|
943
|
-
}
|
|
944
|
-
// RCON相关错误
|
|
945
|
-
if (errorMsg.includes('RCON') || errorMsg.includes('服务器')) {
|
|
946
|
-
if (errorMsg.includes('authentication') || errorMsg.includes('auth') || errorMsg.includes('认证')) {
|
|
947
|
-
return 'RCON认证失败,服务器拒绝访问,请联系管理员检查密码';
|
|
948
|
-
}
|
|
949
|
-
if (errorMsg.includes('ECONNREFUSED') || errorMsg.includes('ETIMEDOUT') || errorMsg.includes('无法连接')) {
|
|
950
|
-
return '无法连接到游戏服务器,请确认服务器是否在线或联系管理员';
|
|
951
|
-
}
|
|
952
|
-
if (errorMsg.includes('command') || errorMsg.includes('执行命令')) {
|
|
953
|
-
return '服务器命令执行失败,请稍后再试';
|
|
954
|
-
}
|
|
955
|
-
return '与游戏服务器通信失败,请稍后再试';
|
|
956
|
-
}
|
|
957
|
-
// 用户名相关错误
|
|
958
|
-
if (errorMsg.includes('用户名') || errorMsg.includes('username')) {
|
|
959
|
-
if (errorMsg.includes('不存在')) {
|
|
960
|
-
return '该Minecraft用户名不存在,请检查拼写';
|
|
961
|
-
}
|
|
962
|
-
if (errorMsg.includes('已被')) {
|
|
963
|
-
return '该Minecraft用户名已被其他用户绑定,请使用其他用户名';
|
|
964
|
-
}
|
|
965
|
-
if (errorMsg.includes('格式')) {
|
|
966
|
-
return 'Minecraft用户名格式不正确,应为3-16位字母、数字和下划线';
|
|
967
|
-
}
|
|
968
|
-
return '用户名验证失败,请检查用户名并重试';
|
|
969
|
-
}
|
|
970
|
-
// 默认错误信息
|
|
971
|
-
return '操作失败,请稍后再试';
|
|
972
|
-
};
|
|
973
|
-
// 判断是否为警告级别错误(用户可能输入有误)
|
|
974
|
-
const isWarningError = (errorMsg) => {
|
|
975
|
-
const warningPatterns = [
|
|
976
|
-
'用户名不存在',
|
|
977
|
-
'格式不正确',
|
|
978
|
-
'已被其他用户绑定',
|
|
979
|
-
'已在白名单中',
|
|
980
|
-
'不在白名单中',
|
|
981
|
-
'未绑定MC账号',
|
|
982
|
-
'冷却期内'
|
|
983
|
-
];
|
|
984
|
-
return warningPatterns.some(pattern => errorMsg.includes(pattern));
|
|
985
|
-
};
|
|
986
|
-
// 判断是否为严重错误(系统问题)
|
|
987
|
-
const isCriticalError = (errorMsg) => {
|
|
988
|
-
const criticalPatterns = [
|
|
989
|
-
'无法连接',
|
|
990
|
-
'RCON认证失败',
|
|
991
|
-
'服务器通信失败',
|
|
992
|
-
'数据库操作出错'
|
|
993
|
-
];
|
|
994
|
-
return criticalPatterns.some(pattern => errorMsg.includes(pattern));
|
|
995
|
-
};
|
|
996
916
|
// 封装发送消息的函数,处理私聊和群聊的不同格式
|
|
997
917
|
const sendMessage = async (session, content, options) => {
|
|
998
918
|
try {
|
|
@@ -1773,41 +1693,11 @@ function apply(ctx, config) {
|
|
|
1773
1693
|
const lowerServerName = serverName.toLowerCase().trim();
|
|
1774
1694
|
// 最小相似度阈值,低于此值的匹配结果将被忽略
|
|
1775
1695
|
const MIN_SIMILARITY = 0.6; // 60%的相似度
|
|
1776
|
-
// 计算Levenshtein距离的函数
|
|
1777
|
-
const levenshteinDistance = (str1, str2) => {
|
|
1778
|
-
const matrix = [];
|
|
1779
|
-
for (let i = 0; i <= str2.length; i++) {
|
|
1780
|
-
matrix[i] = [i];
|
|
1781
|
-
}
|
|
1782
|
-
for (let j = 0; j <= str1.length; j++) {
|
|
1783
|
-
matrix[0][j] = j;
|
|
1784
|
-
}
|
|
1785
|
-
for (let i = 1; i <= str2.length; i++) {
|
|
1786
|
-
for (let j = 1; j <= str1.length; j++) {
|
|
1787
|
-
if (str2.charAt(i - 1) === str1.charAt(j - 1)) {
|
|
1788
|
-
matrix[i][j] = matrix[i - 1][j - 1];
|
|
1789
|
-
}
|
|
1790
|
-
else {
|
|
1791
|
-
matrix[i][j] = Math.min(matrix[i - 1][j - 1] + 1, // 替换
|
|
1792
|
-
matrix[i][j - 1] + 1, // 插入
|
|
1793
|
-
matrix[i - 1][j] + 1 // 删除
|
|
1794
|
-
);
|
|
1795
|
-
}
|
|
1796
|
-
}
|
|
1797
|
-
}
|
|
1798
|
-
return matrix[str2.length][str1.length];
|
|
1799
|
-
};
|
|
1800
|
-
// 计算相似度(0到1之间,1表示完全相同)
|
|
1801
|
-
const calculateSimilarity = (str1, str2) => {
|
|
1802
|
-
const distance = levenshteinDistance(str1, str2);
|
|
1803
|
-
const maxLength = Math.max(str1.length, str2.length);
|
|
1804
|
-
return 1 - distance / maxLength;
|
|
1805
|
-
};
|
|
1806
1696
|
// 查找最相似的服务器名称
|
|
1807
1697
|
let bestMatch = null;
|
|
1808
1698
|
let bestSimilarity = 0;
|
|
1809
1699
|
for (const s of enabledServers) {
|
|
1810
|
-
const similarity = calculateSimilarity(lowerServerName, s.name.toLowerCase().trim());
|
|
1700
|
+
const similarity = (0, helpers_1.calculateSimilarity)(lowerServerName, s.name.toLowerCase().trim());
|
|
1811
1701
|
if (similarity > bestSimilarity && similarity >= MIN_SIMILARITY) {
|
|
1812
1702
|
bestSimilarity = similarity;
|
|
1813
1703
|
bestMatch = s;
|
|
@@ -1861,10 +1751,29 @@ function apply(ctx, config) {
|
|
|
1861
1751
|
checkCooldown,
|
|
1862
1752
|
getCrafatarUrl,
|
|
1863
1753
|
getStarlightSkinUrl,
|
|
1754
|
+
// Database operations (for McidCommandHandler)
|
|
1755
|
+
getMcBindByQQId,
|
|
1756
|
+
getMcBindByUsername,
|
|
1757
|
+
createOrUpdateMcBind,
|
|
1758
|
+
deleteMcBind,
|
|
1759
|
+
checkUsernameExists,
|
|
1760
|
+
checkAndUpdateUsername,
|
|
1761
|
+
// API operations
|
|
1762
|
+
validateUsername,
|
|
1763
|
+
validateBUID,
|
|
1764
|
+
updateBuidInfoOnly,
|
|
1765
|
+
// Permission check functions
|
|
1766
|
+
isAdmin,
|
|
1767
|
+
isMaster,
|
|
1864
1768
|
// Business functions
|
|
1865
1769
|
sendMessage,
|
|
1866
1770
|
autoSetGroupNickname,
|
|
1771
|
+
checkNicknameFormat,
|
|
1867
1772
|
getBindInfo: getMcBindByQQId,
|
|
1773
|
+
// Config operations
|
|
1774
|
+
getServerConfigById,
|
|
1775
|
+
// Error handling
|
|
1776
|
+
getFriendlyErrorMessage: error_utils_1.getFriendlyErrorMessage,
|
|
1868
1777
|
// Service instances
|
|
1869
1778
|
rconManager,
|
|
1870
1779
|
messageUtils,
|
|
@@ -1889,49 +1798,9 @@ function apply(ctx, config) {
|
|
|
1889
1798
|
tagHandler.register();
|
|
1890
1799
|
whitelistHandler.register();
|
|
1891
1800
|
buidHandler.register();
|
|
1892
|
-
// =========== MC命令组 ===========
|
|
1893
|
-
const cmd = ctx.command('mcid', 'Minecraft 账号绑定管理');
|
|
1894
|
-
// 创建McidHandler的依赖对象
|
|
1895
|
-
const mcidHandlerDeps = {
|
|
1896
|
-
config,
|
|
1897
|
-
logger: loggerService,
|
|
1898
|
-
mcidbindRepo,
|
|
1899
|
-
groupExporter,
|
|
1900
|
-
// 辅助函数依赖
|
|
1901
|
-
normalizeQQId,
|
|
1902
|
-
formatCommand,
|
|
1903
|
-
formatUuid,
|
|
1904
|
-
checkCooldown,
|
|
1905
|
-
getCrafatarUrl,
|
|
1906
|
-
getStarlightSkinUrl,
|
|
1907
|
-
// 数据库操作
|
|
1908
|
-
getMcBindByQQId,
|
|
1909
|
-
getMcBindByUsername,
|
|
1910
|
-
createOrUpdateMcBind,
|
|
1911
|
-
deleteMcBind,
|
|
1912
|
-
checkUsernameExists,
|
|
1913
|
-
checkAndUpdateUsername,
|
|
1914
|
-
// API操作
|
|
1915
|
-
validateUsername,
|
|
1916
|
-
validateBUID,
|
|
1917
|
-
updateBuidInfoOnly,
|
|
1918
|
-
// 权限检查
|
|
1919
|
-
isAdmin,
|
|
1920
|
-
isMaster,
|
|
1921
|
-
// 消息操作
|
|
1922
|
-
sendMessage,
|
|
1923
|
-
autoSetGroupNickname,
|
|
1924
|
-
checkNicknameFormat,
|
|
1925
|
-
// 会话管理
|
|
1926
|
-
removeBindingSession,
|
|
1927
|
-
// 服务器配置
|
|
1928
|
-
getServerConfigById,
|
|
1929
|
-
// 工具函数
|
|
1930
|
-
getFriendlyErrorMessage
|
|
1931
|
-
};
|
|
1932
1801
|
// 实例化McidCommandHandler并注册命令
|
|
1933
|
-
const mcidHandler = new handlers_1.McidCommandHandler(ctx,
|
|
1934
|
-
mcidHandler.
|
|
1802
|
+
const mcidHandler = new handlers_1.McidCommandHandler(ctx, config, loggerService, repositories, handlerDependencies);
|
|
1803
|
+
mcidHandler.register();
|
|
1935
1804
|
// 自定义文本前缀匹配
|
|
1936
1805
|
if (config.allowTextPrefix && config.botNickname) {
|
|
1937
1806
|
// 创建一个前缀匹配器
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 错误处理工具函数集合
|
|
3
|
+
* 提供统一的错误信息格式化和分类功能
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* 获取用户友好的错误信息
|
|
7
|
+
* 将技术性错误转换为用户可理解的提示
|
|
8
|
+
* @param error 错误对象或错误消息字符串
|
|
9
|
+
* @returns 格式化后的用户友好错误信息
|
|
10
|
+
*/
|
|
11
|
+
export declare function getFriendlyErrorMessage(error: Error | string): string;
|
|
12
|
+
/**
|
|
13
|
+
* 提取用户友好的错误信息
|
|
14
|
+
* 根据错误消息内容返回对应的用户提示
|
|
15
|
+
* @param errorMsg 原始错误消息
|
|
16
|
+
* @returns 用户可理解的错误提示
|
|
17
|
+
*/
|
|
18
|
+
export declare function getUserFacingErrorMessage(errorMsg: string): string;
|
|
19
|
+
/**
|
|
20
|
+
* 判断是否为警告级别错误(用户可能输入有误)
|
|
21
|
+
* @param errorMsg 错误消息
|
|
22
|
+
* @returns 是否为警告级别错误
|
|
23
|
+
*/
|
|
24
|
+
export declare function isWarningError(errorMsg: string): boolean;
|
|
25
|
+
/**
|
|
26
|
+
* 判断是否为严重错误(系统问题)
|
|
27
|
+
* @param errorMsg 错误消息
|
|
28
|
+
* @returns 是否为严重错误
|
|
29
|
+
*/
|
|
30
|
+
export declare function isCriticalError(errorMsg: string): boolean;
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* 错误处理工具函数集合
|
|
4
|
+
* 提供统一的错误信息格式化和分类功能
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.getFriendlyErrorMessage = getFriendlyErrorMessage;
|
|
8
|
+
exports.getUserFacingErrorMessage = getUserFacingErrorMessage;
|
|
9
|
+
exports.isWarningError = isWarningError;
|
|
10
|
+
exports.isCriticalError = isCriticalError;
|
|
11
|
+
/**
|
|
12
|
+
* 获取用户友好的错误信息
|
|
13
|
+
* 将技术性错误转换为用户可理解的提示
|
|
14
|
+
* @param error 错误对象或错误消息字符串
|
|
15
|
+
* @returns 格式化后的用户友好错误信息
|
|
16
|
+
*/
|
|
17
|
+
function getFriendlyErrorMessage(error) {
|
|
18
|
+
const errorMsg = error instanceof Error ? error.message : error;
|
|
19
|
+
// 拆分错误信息
|
|
20
|
+
const userError = getUserFacingErrorMessage(errorMsg);
|
|
21
|
+
// 将警告级别错误标记出来
|
|
22
|
+
if (isWarningError(userError)) {
|
|
23
|
+
return `⚠️ ${userError}`;
|
|
24
|
+
}
|
|
25
|
+
// 将严重错误标记出来
|
|
26
|
+
if (isCriticalError(userError)) {
|
|
27
|
+
return `❌ ${userError}`;
|
|
28
|
+
}
|
|
29
|
+
return userError;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* 提取用户友好的错误信息
|
|
33
|
+
* 根据错误消息内容返回对应的用户提示
|
|
34
|
+
* @param errorMsg 原始错误消息
|
|
35
|
+
* @returns 用户可理解的错误提示
|
|
36
|
+
*/
|
|
37
|
+
function getUserFacingErrorMessage(errorMsg) {
|
|
38
|
+
// Mojang API相关错误
|
|
39
|
+
if (errorMsg.includes('ECONNABORTED') || errorMsg.includes('timeout')) {
|
|
40
|
+
return '无法连接到Mojang服务器,请稍后再试';
|
|
41
|
+
}
|
|
42
|
+
if (errorMsg.includes('404')) {
|
|
43
|
+
return '该Minecraft用户名不存在';
|
|
44
|
+
}
|
|
45
|
+
if (errorMsg.includes('network') || errorMsg.includes('connect')) {
|
|
46
|
+
return '网络连接异常,请稍后再试';
|
|
47
|
+
}
|
|
48
|
+
// 数据库相关错误
|
|
49
|
+
if (errorMsg.includes('unique') || errorMsg.includes('duplicate')) {
|
|
50
|
+
return '该Minecraft用户名已被其他用户绑定';
|
|
51
|
+
}
|
|
52
|
+
// RCON相关错误
|
|
53
|
+
if (errorMsg.includes('RCON') || errorMsg.includes('服务器')) {
|
|
54
|
+
if (errorMsg.includes('authentication') || errorMsg.includes('auth') || errorMsg.includes('认证')) {
|
|
55
|
+
return 'RCON认证失败,服务器拒绝访问,请联系管理员检查密码';
|
|
56
|
+
}
|
|
57
|
+
if (errorMsg.includes('ECONNREFUSED') || errorMsg.includes('ETIMEDOUT') || errorMsg.includes('无法连接')) {
|
|
58
|
+
return '无法连接到游戏服务器,请确认服务器是否在线或联系管理员';
|
|
59
|
+
}
|
|
60
|
+
if (errorMsg.includes('command') || errorMsg.includes('执行命令')) {
|
|
61
|
+
return '服务器命令执行失败,请稍后再试';
|
|
62
|
+
}
|
|
63
|
+
return '与游戏服务器通信失败,请稍后再试';
|
|
64
|
+
}
|
|
65
|
+
// 用户名相关错误
|
|
66
|
+
if (errorMsg.includes('用户名') || errorMsg.includes('username')) {
|
|
67
|
+
if (errorMsg.includes('不存在')) {
|
|
68
|
+
return '该Minecraft用户名不存在,请检查拼写';
|
|
69
|
+
}
|
|
70
|
+
if (errorMsg.includes('已被')) {
|
|
71
|
+
return '该Minecraft用户名已被其他用户绑定,请使用其他用户名';
|
|
72
|
+
}
|
|
73
|
+
if (errorMsg.includes('格式')) {
|
|
74
|
+
return 'Minecraft用户名格式不正确,应为3-16位字母、数字和下划线';
|
|
75
|
+
}
|
|
76
|
+
return '用户名验证失败,请检查用户名并重试';
|
|
77
|
+
}
|
|
78
|
+
// 默认错误信息
|
|
79
|
+
return '操作失败,请稍后再试';
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* 判断是否为警告级别错误(用户可能输入有误)
|
|
83
|
+
* @param errorMsg 错误消息
|
|
84
|
+
* @returns 是否为警告级别错误
|
|
85
|
+
*/
|
|
86
|
+
function isWarningError(errorMsg) {
|
|
87
|
+
const warningPatterns = [
|
|
88
|
+
'用户名不存在',
|
|
89
|
+
'格式不正确',
|
|
90
|
+
'已被其他用户绑定',
|
|
91
|
+
'已在白名单中',
|
|
92
|
+
'不在白名单中',
|
|
93
|
+
'未绑定MC账号',
|
|
94
|
+
'冷却期内'
|
|
95
|
+
];
|
|
96
|
+
return warningPatterns.some(pattern => errorMsg.includes(pattern));
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* 判断是否为严重错误(系统问题)
|
|
100
|
+
* @param errorMsg 错误消息
|
|
101
|
+
* @returns 是否为严重错误
|
|
102
|
+
*/
|
|
103
|
+
function isCriticalError(errorMsg) {
|
|
104
|
+
const criticalPatterns = [
|
|
105
|
+
'无法连接',
|
|
106
|
+
'RCON认证失败',
|
|
107
|
+
'服务器通信失败',
|
|
108
|
+
'数据库操作出错'
|
|
109
|
+
];
|
|
110
|
+
return criticalPatterns.some(pattern => errorMsg.includes(pattern));
|
|
111
|
+
}
|
package/lib/utils/helpers.d.ts
CHANGED
|
@@ -74,3 +74,18 @@ export declare function escapeRegExp(string: string): string;
|
|
|
74
74
|
* @returns 清理后的输入内容
|
|
75
75
|
*/
|
|
76
76
|
export declare function cleanUserInput(content: string, session: Session, botNickname: string, logger?: Logger): string;
|
|
77
|
+
/**
|
|
78
|
+
* 计算两个字符串之间的Levenshtein距离
|
|
79
|
+
* Levenshtein距离是指将一个字符串转换成另一个字符串所需的最少编辑操作次数
|
|
80
|
+
* @param str1 第一个字符串
|
|
81
|
+
* @param str2 第二个字符串
|
|
82
|
+
* @returns 两个字符串之间的编辑距离
|
|
83
|
+
*/
|
|
84
|
+
export declare function levenshteinDistance(str1: string, str2: string): number;
|
|
85
|
+
/**
|
|
86
|
+
* 计算两个字符串的相似度(基于Levenshtein距离)
|
|
87
|
+
* @param str1 第一个字符串
|
|
88
|
+
* @param str2 第二个字符串
|
|
89
|
+
* @returns 相似度值(0到1之间,1表示完全相同)
|
|
90
|
+
*/
|
|
91
|
+
export declare function calculateSimilarity(str1: string, str2: string): number;
|
package/lib/utils/helpers.js
CHANGED
|
@@ -9,6 +9,8 @@ exports.getStarlightSkinUrl = getStarlightSkinUrl;
|
|
|
9
9
|
exports.checkIrrelevantInput = checkIrrelevantInput;
|
|
10
10
|
exports.escapeRegExp = escapeRegExp;
|
|
11
11
|
exports.cleanUserInput = cleanUserInput;
|
|
12
|
+
exports.levenshteinDistance = levenshteinDistance;
|
|
13
|
+
exports.calculateSimilarity = calculateSimilarity;
|
|
12
14
|
/**
|
|
13
15
|
* 通用工具函数集合
|
|
14
16
|
*/
|
|
@@ -273,3 +275,47 @@ function cleanUserInput(content, session, botNickname, logger) {
|
|
|
273
275
|
}
|
|
274
276
|
return cleanedContent;
|
|
275
277
|
}
|
|
278
|
+
/**
|
|
279
|
+
* 计算两个字符串之间的Levenshtein距离
|
|
280
|
+
* Levenshtein距离是指将一个字符串转换成另一个字符串所需的最少编辑操作次数
|
|
281
|
+
* @param str1 第一个字符串
|
|
282
|
+
* @param str2 第二个字符串
|
|
283
|
+
* @returns 两个字符串之间的编辑距离
|
|
284
|
+
*/
|
|
285
|
+
function levenshteinDistance(str1, str2) {
|
|
286
|
+
const matrix = [];
|
|
287
|
+
// 初始化第一列
|
|
288
|
+
for (let i = 0; i <= str2.length; i++) {
|
|
289
|
+
matrix[i] = [i];
|
|
290
|
+
}
|
|
291
|
+
// 初始化第一行
|
|
292
|
+
for (let j = 0; j <= str1.length; j++) {
|
|
293
|
+
matrix[0][j] = j;
|
|
294
|
+
}
|
|
295
|
+
// 填充矩阵
|
|
296
|
+
for (let i = 1; i <= str2.length; i++) {
|
|
297
|
+
for (let j = 1; j <= str1.length; j++) {
|
|
298
|
+
if (str2.charAt(i - 1) === str1.charAt(j - 1)) {
|
|
299
|
+
matrix[i][j] = matrix[i - 1][j - 1];
|
|
300
|
+
}
|
|
301
|
+
else {
|
|
302
|
+
matrix[i][j] = Math.min(matrix[i - 1][j - 1] + 1, // 替换
|
|
303
|
+
matrix[i][j - 1] + 1, // 插入
|
|
304
|
+
matrix[i - 1][j] + 1 // 删除
|
|
305
|
+
);
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
return matrix[str2.length][str1.length];
|
|
310
|
+
}
|
|
311
|
+
/**
|
|
312
|
+
* 计算两个字符串的相似度(基于Levenshtein距离)
|
|
313
|
+
* @param str1 第一个字符串
|
|
314
|
+
* @param str2 第二个字符串
|
|
315
|
+
* @returns 相似度值(0到1之间,1表示完全相同)
|
|
316
|
+
*/
|
|
317
|
+
function calculateSimilarity(str1, str2) {
|
|
318
|
+
const distance = levenshteinDistance(str1, str2);
|
|
319
|
+
const maxLength = Math.max(str1.length, str2.length);
|
|
320
|
+
return 1 - distance / maxLength;
|
|
321
|
+
}
|
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "koishi-plugin-bind-bot",
|
|
3
3
|
"description": "[WittF自用] BIND-BOT - 账号绑定管理机器人,支持Minecraft账号和B站账号绑定与管理。",
|
|
4
|
-
"version": "2.0.
|
|
4
|
+
"version": "2.0.2",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"typings": "lib/index.d.ts",
|
|
7
7
|
"files": [
|
|
8
8
|
"lib"
|
|
9
9
|
],
|
|
10
|
-
"license": "
|
|
10
|
+
"license": "CC-BY-NC-SA-4.0",
|
|
11
11
|
"scripts": {
|
|
12
12
|
"build": "tsc"
|
|
13
13
|
},
|