koishi-plugin-maple-dice-v2 0.0.1 → 0.0.3
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/lib/index.js +587 -598
- package/package.json +1 -1
- package/lib/index.d.ts +0 -23
package/lib/index.js
CHANGED
|
@@ -1,607 +1,596 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
throw new Error('一次最多只能掷 100 个骰子');
|
|
28
|
-
}
|
|
29
|
-
const rolls = [];
|
|
30
|
-
for (let i = 0; i < count; i++) {
|
|
31
|
-
rolls.push(Math.floor(Math.random() * sides) + 1);
|
|
32
|
-
}
|
|
33
|
-
const diceTotal = rolls.reduce((sum, roll) => sum + roll, 0);
|
|
34
|
-
let total;
|
|
35
|
-
switch (operator) {
|
|
36
|
-
case '+':
|
|
37
|
-
total = diceTotal + modifier;
|
|
38
|
-
break;
|
|
39
|
-
case '-':
|
|
40
|
-
total = diceTotal - modifier;
|
|
41
|
-
break;
|
|
42
|
-
case '*':
|
|
43
|
-
total = diceTotal * modifier;
|
|
44
|
-
break;
|
|
45
|
-
case '/':
|
|
46
|
-
if (modifier === 0) {
|
|
47
|
-
throw new Error('除数不能为0');
|
|
48
|
-
}
|
|
49
|
-
total = Math.floor(diceTotal / modifier); // 向下取整
|
|
50
|
-
break;
|
|
51
|
-
default:
|
|
52
|
-
total = diceTotal;
|
|
53
|
-
}
|
|
54
|
-
let expr = `${count}d${sides}`;
|
|
55
|
-
if (operator) {
|
|
56
|
-
expr += `${operator}${modifier}`;
|
|
57
|
-
}
|
|
58
|
-
return {
|
|
59
|
-
total,
|
|
60
|
-
details: rolls,
|
|
61
|
-
expression: expr,
|
|
62
|
-
operator,
|
|
63
|
-
modifier,
|
|
64
|
-
count,
|
|
65
|
-
sides
|
|
66
|
-
};
|
|
67
|
-
}
|
|
68
|
-
// 技能检定
|
|
69
|
-
static skillCheck(skillValue) {
|
|
70
|
-
const diceValue = Math.floor(Math.random() * 100) + 1;
|
|
71
|
-
// 判断成功等级
|
|
72
|
-
let successLevel = '';
|
|
73
|
-
if (diceValue === 1) {
|
|
74
|
-
successLevel = 'greatSuccess'; // 大成功
|
|
75
|
-
}
|
|
76
|
-
else if (diceValue === 100) {
|
|
77
|
-
successLevel = 'greatFail'; // 大失败
|
|
78
|
-
}
|
|
79
|
-
else if (diceValue <= Math.floor(skillValue / 5)) {
|
|
80
|
-
successLevel = 'extremeSuccess'; // 极难成功
|
|
81
|
-
}
|
|
82
|
-
else if (diceValue <= Math.floor(skillValue / 2)) {
|
|
83
|
-
successLevel = 'hardSuccess'; // 困难成功
|
|
84
|
-
}
|
|
85
|
-
else if (diceValue <= skillValue) {
|
|
86
|
-
successLevel = 'success'; // 成功
|
|
87
|
-
}
|
|
88
|
-
else {
|
|
89
|
-
successLevel = 'fail'; // 失败
|
|
90
|
-
}
|
|
91
|
-
return {
|
|
92
|
-
diceValue,
|
|
93
|
-
skillValue,
|
|
94
|
-
successLevel
|
|
95
|
-
};
|
|
96
|
-
}
|
|
97
|
-
// 奖励骰/惩罚骰检定
|
|
98
|
-
static bonusPenaltyCheck(tensCount, skillValue, isReward) {
|
|
99
|
-
// 生成十位数的备选结果
|
|
100
|
-
const tens = [];
|
|
101
|
-
for (let i = 0; i < tensCount; i++) {
|
|
102
|
-
tens.push(Math.floor(Math.random() * 10)); // 0-9
|
|
103
|
-
}
|
|
104
|
-
// 生成个位数
|
|
105
|
-
const unit = Math.floor(Math.random() * 10); // 0-9
|
|
106
|
-
// 选择十位数:奖励骰取最小,惩罚骰取最大
|
|
107
|
-
let selectedTen;
|
|
108
|
-
if (isReward) {
|
|
109
|
-
selectedTen = Math.min(...tens);
|
|
110
|
-
}
|
|
111
|
-
else {
|
|
112
|
-
selectedTen = Math.max(...tens);
|
|
113
|
-
}
|
|
114
|
-
// 组合成最终骰值 (0-99, 0表示100)
|
|
115
|
-
let diceValue = selectedTen * 10 + unit;
|
|
116
|
-
if (diceValue === 0) {
|
|
117
|
-
diceValue = 100;
|
|
118
|
-
}
|
|
119
|
-
// 判断成功等级
|
|
120
|
-
let successLevel = '';
|
|
121
|
-
if (diceValue === 1) {
|
|
122
|
-
successLevel = 'greatSuccess'; // 大成功
|
|
123
|
-
}
|
|
124
|
-
else if (diceValue === 100) {
|
|
125
|
-
successLevel = 'greatFail'; // 大失败
|
|
126
|
-
}
|
|
127
|
-
else if (diceValue <= Math.floor(skillValue / 5)) {
|
|
128
|
-
successLevel = 'extremeSuccess'; // 极难成功
|
|
129
|
-
}
|
|
130
|
-
else if (diceValue <= Math.floor(skillValue / 2)) {
|
|
131
|
-
successLevel = 'hardSuccess'; // 困难成功
|
|
132
|
-
}
|
|
133
|
-
else if (diceValue <= skillValue) {
|
|
134
|
-
successLevel = 'success'; // 成功
|
|
135
|
-
}
|
|
136
|
-
else {
|
|
137
|
-
successLevel = 'fail'; // 失败
|
|
138
|
-
}
|
|
139
|
-
return {
|
|
140
|
-
diceValue,
|
|
141
|
-
skillValue,
|
|
142
|
-
successLevel,
|
|
143
|
-
tens,
|
|
144
|
-
unit
|
|
145
|
-
};
|
|
146
|
-
}
|
|
147
|
-
// 获取成功等级的描述
|
|
148
|
-
static getSuccessLevelText(level) {
|
|
149
|
-
const texts = {
|
|
150
|
-
'greatSuccess': '大成功',
|
|
151
|
-
'greatFail': '大失败',
|
|
152
|
-
'extremeSuccess': '极难成功',
|
|
153
|
-
'hardSuccess': '困难成功',
|
|
154
|
-
'success': '成功',
|
|
155
|
-
'fail': '失败'
|
|
156
|
-
};
|
|
157
|
-
return texts[level] || level;
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
// 配置定义
|
|
161
|
-
export const Config = Schema.object({
|
|
162
|
-
defaultSkill: Schema.number()
|
|
163
|
-
.default(50)
|
|
164
|
-
.min(1)
|
|
165
|
-
.max(100)
|
|
166
|
-
.description('默认技能值(当ra指令未指定时使用)'),
|
|
167
|
-
replyMode: Schema.union([
|
|
168
|
-
Schema.const('global').description('全局: 调用所有自定义回复'),
|
|
169
|
-
Schema.const('group').description('群组: 仅调用当前群组内添加的所有自定义回复(私聊时,仅调用本人私聊添加的所有自定义回复)'),
|
|
170
|
-
Schema.const('personal').description('个人: 仅调用由本人添加的所有自定义回复')
|
|
171
|
-
])
|
|
172
|
-
.default('global')
|
|
173
|
-
.description('回复模式'),
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
5
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name2 in all)
|
|
8
|
+
__defProp(target, name2, { get: all[name2], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var src_exports = {};
|
|
22
|
+
__export(src_exports, {
|
|
23
|
+
Config: () => Config,
|
|
24
|
+
apply: () => apply,
|
|
25
|
+
name: () => name,
|
|
26
|
+
using: () => using
|
|
174
27
|
});
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
28
|
+
module.exports = __toCommonJS(src_exports);
|
|
29
|
+
var import_koishi = require("koishi");
|
|
30
|
+
var name = "maple-dice-v2";
|
|
31
|
+
var using = ["database"];
|
|
32
|
+
var DiceRoller = class {
|
|
33
|
+
static {
|
|
34
|
+
__name(this, "DiceRoller");
|
|
35
|
+
}
|
|
36
|
+
static parseDice(expression) {
|
|
37
|
+
if (!expression) {
|
|
38
|
+
expression = "1d100";
|
|
39
|
+
}
|
|
40
|
+
expression = expression.replace(/\s+/g, "").toLowerCase();
|
|
41
|
+
const diceRegex = /^(\d+)?d(\d+)(?:([+\-*/])(\d+))?$/;
|
|
42
|
+
const match = expression.match(diceRegex);
|
|
43
|
+
if (!match) {
|
|
44
|
+
throw new Error("无效的掷骰表达式。正确格式: r xdy[+-*/]z");
|
|
45
|
+
}
|
|
46
|
+
const count = match[1] ? parseInt(match[1]) : 1;
|
|
47
|
+
const sides = parseInt(match[2]);
|
|
48
|
+
const operator = match[3] || "";
|
|
49
|
+
const modifier = match[4] ? parseInt(match[4]) : 0;
|
|
50
|
+
if (count < 1 || sides < 1) {
|
|
51
|
+
throw new Error("骰子数量和面数必须为正整数");
|
|
52
|
+
}
|
|
53
|
+
if (count > 100) {
|
|
54
|
+
throw new Error("一次最多只能掷 100 个骰子");
|
|
55
|
+
}
|
|
56
|
+
const rolls = [];
|
|
57
|
+
for (let i = 0; i < count; i++) {
|
|
58
|
+
rolls.push(Math.floor(Math.random() * sides) + 1);
|
|
59
|
+
}
|
|
60
|
+
const diceTotal = rolls.reduce((sum, roll) => sum + roll, 0);
|
|
61
|
+
let total;
|
|
62
|
+
switch (operator) {
|
|
63
|
+
case "+":
|
|
64
|
+
total = diceTotal + modifier;
|
|
65
|
+
break;
|
|
66
|
+
case "-":
|
|
67
|
+
total = diceTotal - modifier;
|
|
68
|
+
break;
|
|
69
|
+
case "*":
|
|
70
|
+
total = diceTotal * modifier;
|
|
71
|
+
break;
|
|
72
|
+
case "/":
|
|
73
|
+
if (modifier === 0) {
|
|
74
|
+
throw new Error("除数不能为0");
|
|
75
|
+
}
|
|
76
|
+
total = Math.floor(diceTotal / modifier);
|
|
77
|
+
break;
|
|
78
|
+
default:
|
|
79
|
+
total = diceTotal;
|
|
80
|
+
}
|
|
81
|
+
let expr = `${count}d${sides}`;
|
|
82
|
+
if (operator) {
|
|
83
|
+
expr += `${operator}${modifier}`;
|
|
84
|
+
}
|
|
85
|
+
return {
|
|
86
|
+
total,
|
|
87
|
+
details: rolls,
|
|
88
|
+
expression: expr,
|
|
89
|
+
operator,
|
|
90
|
+
modifier,
|
|
91
|
+
count,
|
|
92
|
+
sides
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
// 技能检定
|
|
96
|
+
static skillCheck(skillValue) {
|
|
97
|
+
const diceValue = Math.floor(Math.random() * 100) + 1;
|
|
98
|
+
let successLevel = "";
|
|
99
|
+
if (diceValue === 1) {
|
|
100
|
+
successLevel = "greatSuccess";
|
|
101
|
+
} else if (diceValue === 100) {
|
|
102
|
+
successLevel = "greatFail";
|
|
103
|
+
} else if (diceValue <= Math.floor(skillValue / 5)) {
|
|
104
|
+
successLevel = "extremeSuccess";
|
|
105
|
+
} else if (diceValue <= Math.floor(skillValue / 2)) {
|
|
106
|
+
successLevel = "hardSuccess";
|
|
107
|
+
} else if (diceValue <= skillValue) {
|
|
108
|
+
successLevel = "success";
|
|
109
|
+
} else {
|
|
110
|
+
successLevel = "fail";
|
|
111
|
+
}
|
|
112
|
+
return {
|
|
113
|
+
diceValue,
|
|
114
|
+
skillValue,
|
|
115
|
+
successLevel
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
// 奖励骰/惩罚骰检定
|
|
119
|
+
static bonusPenaltyCheck(tensCount, skillValue, isReward) {
|
|
120
|
+
const tens = [];
|
|
121
|
+
for (let i = 0; i < tensCount; i++) {
|
|
122
|
+
tens.push(Math.floor(Math.random() * 10));
|
|
123
|
+
}
|
|
124
|
+
const unit = Math.floor(Math.random() * 10);
|
|
125
|
+
let selectedTen;
|
|
126
|
+
if (isReward) {
|
|
127
|
+
selectedTen = Math.min(...tens);
|
|
128
|
+
} else {
|
|
129
|
+
selectedTen = Math.max(...tens);
|
|
130
|
+
}
|
|
131
|
+
let diceValue = selectedTen * 10 + unit;
|
|
132
|
+
if (diceValue === 0) {
|
|
133
|
+
diceValue = 100;
|
|
134
|
+
}
|
|
135
|
+
let successLevel = "";
|
|
136
|
+
if (diceValue === 1) {
|
|
137
|
+
successLevel = "greatSuccess";
|
|
138
|
+
} else if (diceValue === 100) {
|
|
139
|
+
successLevel = "greatFail";
|
|
140
|
+
} else if (diceValue <= Math.floor(skillValue / 5)) {
|
|
141
|
+
successLevel = "extremeSuccess";
|
|
142
|
+
} else if (diceValue <= Math.floor(skillValue / 2)) {
|
|
143
|
+
successLevel = "hardSuccess";
|
|
144
|
+
} else if (diceValue <= skillValue) {
|
|
145
|
+
successLevel = "success";
|
|
146
|
+
} else {
|
|
147
|
+
successLevel = "fail";
|
|
148
|
+
}
|
|
149
|
+
return {
|
|
150
|
+
diceValue,
|
|
151
|
+
skillValue,
|
|
152
|
+
successLevel,
|
|
153
|
+
tens,
|
|
154
|
+
unit
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
// 获取成功等级的描述
|
|
158
|
+
static getSuccessLevelText(level) {
|
|
159
|
+
const texts = {
|
|
160
|
+
"greatSuccess": "大成功",
|
|
161
|
+
"greatFail": "大失败",
|
|
162
|
+
"extremeSuccess": "极难成功",
|
|
163
|
+
"hardSuccess": "困难成功",
|
|
164
|
+
"success": "成功",
|
|
165
|
+
"fail": "失败"
|
|
166
|
+
};
|
|
167
|
+
return texts[level] || level;
|
|
168
|
+
}
|
|
183
169
|
};
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
170
|
+
var Config = import_koishi.Schema.object({
|
|
171
|
+
defaultSkill: import_koishi.Schema.number().default(50).min(1).max(100).description("默认技能值(当ra指令未指定时使用)"),
|
|
172
|
+
replyMode: import_koishi.Schema.union([
|
|
173
|
+
import_koishi.Schema.const("global").description("全局: 调用所有自定义回复"),
|
|
174
|
+
import_koishi.Schema.const("group").description("群组: 仅调用当前群组内添加的所有自定义回复(私聊时,仅调用本人私聊添加的所有自定义回复)"),
|
|
175
|
+
import_koishi.Schema.const("personal").description("个人: 仅调用由本人添加的所有自定义回复")
|
|
176
|
+
]).default("global").description("回复模式")
|
|
177
|
+
});
|
|
178
|
+
var keyToLevelName = {
|
|
179
|
+
"greatSuccess": "大成功",
|
|
180
|
+
"greatFail": "大失败",
|
|
181
|
+
"extremeSuccess": "极难成功",
|
|
182
|
+
"hardSuccess": "困难成功",
|
|
183
|
+
"success": "成功",
|
|
184
|
+
"fail": "失败"
|
|
191
185
|
};
|
|
192
|
-
// 根据回复模式和会话信息筛选回复
|
|
193
186
|
function filterResponsesByMode(responses, session, replyMode, levelName) {
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
r.author === userId);
|
|
215
|
-
default:
|
|
216
|
-
// 默认返回全局模式
|
|
217
|
-
return responses.filter(r => r.level === levelName);
|
|
218
|
-
}
|
|
187
|
+
if (responses.length === 0) {
|
|
188
|
+
return [];
|
|
189
|
+
}
|
|
190
|
+
const isPrivate = !session.guildId;
|
|
191
|
+
const userId = session.userId;
|
|
192
|
+
const groupId = isPrivate ? "私聊" : session.guildId;
|
|
193
|
+
switch (replyMode) {
|
|
194
|
+
case "global":
|
|
195
|
+
return responses.filter((r) => r.level === levelName);
|
|
196
|
+
case "group":
|
|
197
|
+
return responses.filter(
|
|
198
|
+
(r) => r.level === levelName && r.group === groupId
|
|
199
|
+
);
|
|
200
|
+
case "personal":
|
|
201
|
+
return responses.filter(
|
|
202
|
+
(r) => r.level === levelName && r.author === userId
|
|
203
|
+
);
|
|
204
|
+
default:
|
|
205
|
+
return responses.filter((r) => r.level === levelName);
|
|
206
|
+
}
|
|
219
207
|
}
|
|
220
|
-
|
|
208
|
+
__name(filterResponsesByMode, "filterResponsesByMode");
|
|
221
209
|
async function getRandomResponse(ctx, session, config, successLevel, diceValue, skillValue) {
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
const
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
replies = filteredResponses.map(r => r.content);
|
|
243
|
-
}
|
|
244
|
-
const randomResponse = replies[Math.floor(Math.random() * replies.length)];
|
|
245
|
-
// 替换变量
|
|
246
|
-
const levelText = DiceRoller.getSuccessLevelText(successLevel);
|
|
247
|
-
return randomResponse
|
|
248
|
-
.replace(/{result}/g, diceValue.toString())
|
|
249
|
-
.replace(/{skill}/g, skillValue.toString())
|
|
250
|
-
.replace(/{level}/g, levelText);
|
|
210
|
+
const levelName = keyToLevelName[successLevel] || "成功";
|
|
211
|
+
const allResponses = await ctx.database.get("maple-dice-responses", {});
|
|
212
|
+
const filteredResponses = filterResponsesByMode(allResponses, session, config.replyMode, levelName);
|
|
213
|
+
let replies = [];
|
|
214
|
+
if (filteredResponses.length === 0) {
|
|
215
|
+
const defaultResponses = {
|
|
216
|
+
"大成功": ["大成功!骰值:{result}"],
|
|
217
|
+
"大失败": ["大失败!骰值:{result}"],
|
|
218
|
+
"极难成功": ["极难成功!骰值:{result}"],
|
|
219
|
+
"困难成功": ["困难成功!骰值:{result}"],
|
|
220
|
+
"成功": ["成功!骰值:{result}"],
|
|
221
|
+
"失败": ["失败!骰值:{result}"]
|
|
222
|
+
};
|
|
223
|
+
replies = defaultResponses[levelName] || ["{level}!骰值:{result}"];
|
|
224
|
+
} else {
|
|
225
|
+
replies = filteredResponses.map((r) => r.content);
|
|
226
|
+
}
|
|
227
|
+
const randomResponse = replies[Math.floor(Math.random() * replies.length)];
|
|
228
|
+
const levelText = DiceRoller.getSuccessLevelText(successLevel);
|
|
229
|
+
return randomResponse.replace(/{result}/g, diceValue.toString()).replace(/{skill}/g, skillValue.toString()).replace(/{level}/g, levelText);
|
|
251
230
|
}
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
.
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
})
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
.
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
const
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
// 显示所有等级
|
|
515
|
-
const modeText = {
|
|
516
|
-
'all': '所有',
|
|
517
|
-
'group': `当前${isPrivate ? '私聊' : '群组'}`,
|
|
518
|
-
'personal': '本人'
|
|
519
|
-
}[mode];
|
|
520
|
-
let output = `${modeText}自定义回复:\n\n`;
|
|
521
|
-
const levelNames = ['大成功', '极难成功', '困难成功', '成功', '失败', '大失败'];
|
|
522
|
-
for (const levelName of levelNames) {
|
|
523
|
-
const levelResponses = grouped[levelName] || [];
|
|
524
|
-
if (levelResponses.length > 0) {
|
|
525
|
-
output += `【${levelName}】(${levelResponses.length}条):\n`;
|
|
526
|
-
output += levelResponses.map((r, index) => {
|
|
527
|
-
const isOwner = userId && r.author === userId;
|
|
528
|
-
return `${index + 1}. [ID:${r.id}] ${r.content} ${isOwner ? '(可修改)' : ''}`;
|
|
529
|
-
}).join('\n');
|
|
530
|
-
output += '\n\n';
|
|
531
|
-
}
|
|
532
|
-
}
|
|
533
|
-
return output.trim();
|
|
534
|
-
}
|
|
535
|
-
});
|
|
536
|
-
// 删除自定义回复指令 - 检查作者权限
|
|
537
|
-
ctx.command('删除自定义回复 <id:number>', '删除自定义回复')
|
|
538
|
-
.alias('删除回复')
|
|
539
|
-
.example('删除自定义回复 1 删除ID为1的回复')
|
|
540
|
-
.action(async ({ session }, id) => {
|
|
541
|
-
// 检查用户ID是否存在
|
|
542
|
-
if (!session?.userId) {
|
|
543
|
-
return '无法获取用户信息,请确保在正确的环境下使用此指令';
|
|
544
|
-
}
|
|
545
|
-
// 检查ID是否存在
|
|
546
|
-
const existing = await ctx.database.get('maple-dice-responses', { id });
|
|
547
|
-
if (existing.length === 0) {
|
|
548
|
-
return `未找到ID为${id}的回复`;
|
|
549
|
-
}
|
|
550
|
-
// 检查权限:只能删除自己添加的回复
|
|
551
|
-
const response = existing[0];
|
|
552
|
-
if (response.author !== session.userId) {
|
|
553
|
-
return `无法删除此回复,您只能删除自己添加的回复。\n输入【查看自定义回复 -m】查看由自己添加的回复`;
|
|
554
|
-
}
|
|
555
|
-
// 获取要删除的回复内容
|
|
556
|
-
const contentToDelete = response.content;
|
|
557
|
-
const level = response.level;
|
|
558
|
-
// 删除回复
|
|
559
|
-
await ctx.database.remove('maple-dice-responses', { id });
|
|
560
|
-
return `已删除【${level}】的回复(ID: ${id}):\n${contentToDelete}`;
|
|
561
|
-
});
|
|
562
|
-
// 修改自定义回复指令 - 检查作者权限
|
|
563
|
-
ctx.command('修改自定义回复 <id:number> <text:string>', '修改自定义回复')
|
|
564
|
-
.alias('修改回复')
|
|
565
|
-
.example('修改自定义回复 1 新的回复内容')
|
|
566
|
-
.action(async ({ session }, id, text) => {
|
|
567
|
-
// 检查用户ID是否存在
|
|
568
|
-
if (!session?.userId) {
|
|
569
|
-
return '无法获取用户信息,请确保在正确的环境下使用此指令';
|
|
570
|
-
}
|
|
571
|
-
// 检查ID是否存在
|
|
572
|
-
const existing = await ctx.database.get('maple-dice-responses', { id });
|
|
573
|
-
if (existing.length === 0) {
|
|
574
|
-
return `未找到ID为${id}的回复`;
|
|
575
|
-
}
|
|
576
|
-
// 检查权限:只能修改自己添加的回复
|
|
577
|
-
const response = existing[0];
|
|
578
|
-
if (response.author !== session.userId) {
|
|
579
|
-
return `无法修改此回复,您只能修改自己添加的回复。\n输入【查看自定义回复 -m】查看由自己添加的回复`;
|
|
580
|
-
}
|
|
581
|
-
// 检查新内容是否为空
|
|
582
|
-
if (!text.trim()) {
|
|
583
|
-
return '新回复内容不能为空';
|
|
584
|
-
}
|
|
585
|
-
// 获取旧内容和等级
|
|
586
|
-
const oldContent = response.content;
|
|
587
|
-
const level = response.level;
|
|
588
|
-
// 修改回复
|
|
589
|
-
await ctx.database.set('maple-dice-responses', { id }, {
|
|
590
|
-
content: text.trim(),
|
|
591
|
-
created: new Date(), // 更新修改时间
|
|
592
|
-
});
|
|
593
|
-
return `已修改【${level}】的回复(ID: ${id}):\n原内容: ${oldContent}\n新内容: ${text.trim()}`;
|
|
594
|
-
});
|
|
595
|
-
// 清空所有自定义回复指令 - 不进行作者限制
|
|
596
|
-
ctx.command('清空自定义回复', '清空所有自定义回复')
|
|
597
|
-
.alias('清空回复')
|
|
598
|
-
.action(async () => {
|
|
599
|
-
const count = await ctx.database.remove('maple-dice-responses', {});
|
|
600
|
-
return `已清空所有 ${count} 条自定义回复`;
|
|
601
|
-
});
|
|
602
|
-
ctx.on('ready', () => {
|
|
603
|
-
console.log('maple-dice-v2 插件已加载完成');
|
|
604
|
-
ctx.logger('maple-dice-v2').info(`默认技能值: ${config.defaultSkill}`);
|
|
605
|
-
ctx.logger('maple-dice-v2').info(`回复模式: ${config.replyMode}`);
|
|
231
|
+
__name(getRandomResponse, "getRandomResponse");
|
|
232
|
+
function apply(ctx, config) {
|
|
233
|
+
console.log("maple-dice-v2 插件加载中...");
|
|
234
|
+
ctx.model.extend("maple-dice-responses", {
|
|
235
|
+
id: "unsigned",
|
|
236
|
+
level: "string",
|
|
237
|
+
content: "text",
|
|
238
|
+
author: "string",
|
|
239
|
+
group: "string",
|
|
240
|
+
// 添加群字段
|
|
241
|
+
created: "timestamp"
|
|
242
|
+
}, {
|
|
243
|
+
primary: "id",
|
|
244
|
+
autoInc: true
|
|
245
|
+
});
|
|
246
|
+
ctx.command("r [expression:string]", "基础掷骰(默认为1d100)").alias("roll").alias("掷骰").example("r 3d6 掷3个6面骰").example("r 2d20+5 掷2个20面骰并加5").action(async ({ session }, expression) => {
|
|
247
|
+
try {
|
|
248
|
+
const result = DiceRoller.parseDice(expression);
|
|
249
|
+
let output = `r ${result.expression} = `;
|
|
250
|
+
if (!result.operator) {
|
|
251
|
+
if (result.count === 1) {
|
|
252
|
+
output += `${result.total}`;
|
|
253
|
+
} else {
|
|
254
|
+
output += `${result.details.join("+")} = ${result.total}`;
|
|
255
|
+
}
|
|
256
|
+
} else {
|
|
257
|
+
if (result.count === 1) {
|
|
258
|
+
output += `${result.details[0]}${result.operator}${result.modifier} = ${result.total}`;
|
|
259
|
+
} else {
|
|
260
|
+
output += `(${result.details.join("+")})${result.operator}${result.modifier} = ${result.total}`;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
return output;
|
|
264
|
+
} catch (error) {
|
|
265
|
+
return `错误: ${error.message}`;
|
|
266
|
+
}
|
|
267
|
+
});
|
|
268
|
+
ctx.command("ra [skill:number]", "技能检定").alias("检定").example("ra 使用默认技能值进行检定").example("ra 80 使用80点技能值进行检定").action(async ({ session }, skill) => {
|
|
269
|
+
const skillValue = skill || config.defaultSkill;
|
|
270
|
+
if (skillValue < 1 || skillValue > 100) {
|
|
271
|
+
return "技能值必须在1-100之间";
|
|
272
|
+
}
|
|
273
|
+
const result = DiceRoller.skillCheck(skillValue);
|
|
274
|
+
const response = await getRandomResponse(ctx, session, config, result.successLevel, result.diceValue, skillValue);
|
|
275
|
+
const levelText = DiceRoller.getSuccessLevelText(result.successLevel);
|
|
276
|
+
return `ra ${skillValue}=${result.diceValue}/${skillValue} ${levelText}
|
|
277
|
+
${response}`;
|
|
278
|
+
});
|
|
279
|
+
ctx.command("rb <input:string>", "奖励骰检定").example("rb 3/70 进行3个奖励骰的70点技能检定").example("rb 2 进行2个奖励骰,使用默认技能值").action(async ({ session }, input) => {
|
|
280
|
+
try {
|
|
281
|
+
const parts = input.split("/");
|
|
282
|
+
const tensCount = parseInt(parts[0]);
|
|
283
|
+
if (isNaN(tensCount) || tensCount < 1) {
|
|
284
|
+
return "奖励骰数量必须是正整数";
|
|
285
|
+
}
|
|
286
|
+
let skillValue = config.defaultSkill;
|
|
287
|
+
if (parts.length > 1) {
|
|
288
|
+
skillValue = parseInt(parts[1]);
|
|
289
|
+
if (isNaN(skillValue) || skillValue < 1 || skillValue > 100) {
|
|
290
|
+
return "技能值必须在1-100之间";
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
const result = DiceRoller.bonusPenaltyCheck(tensCount, skillValue, true);
|
|
294
|
+
const response = await getRandomResponse(ctx, session, config, result.successLevel, result.diceValue, skillValue);
|
|
295
|
+
const levelText = DiceRoller.getSuccessLevelText(result.successLevel);
|
|
296
|
+
const tensDisplay = `[${result.tens.join(",")}]`;
|
|
297
|
+
const unitDisplay = `[${result.unit}]`;
|
|
298
|
+
return `rb ${tensCount}/${skillValue}=${tensDisplay}+${unitDisplay}=${result.diceValue}/${skillValue} ${levelText}
|
|
299
|
+
${response}`;
|
|
300
|
+
} catch (error) {
|
|
301
|
+
return `错误: ${error.message}`;
|
|
302
|
+
}
|
|
303
|
+
});
|
|
304
|
+
ctx.command("rp <input:string>", "惩罚骰检定").example("rp 3/70 进行3个惩罚骰的70点技能检定").example("rp 2 进行2个惩罚骰,使用默认技能值").action(async ({ session }, input) => {
|
|
305
|
+
try {
|
|
306
|
+
const parts = input.split("/");
|
|
307
|
+
const tensCount = parseInt(parts[0]);
|
|
308
|
+
if (isNaN(tensCount) || tensCount < 1) {
|
|
309
|
+
return "惩罚骰数量必须是正整数";
|
|
310
|
+
}
|
|
311
|
+
let skillValue = config.defaultSkill;
|
|
312
|
+
if (parts.length > 1) {
|
|
313
|
+
skillValue = parseInt(parts[1]);
|
|
314
|
+
if (isNaN(skillValue) || skillValue < 1 || skillValue > 100) {
|
|
315
|
+
return "技能值必须在1-100之间";
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
const result = DiceRoller.bonusPenaltyCheck(tensCount, skillValue, false);
|
|
319
|
+
const response = await getRandomResponse(ctx, session, config, result.successLevel, result.diceValue, skillValue);
|
|
320
|
+
const levelText = DiceRoller.getSuccessLevelText(result.successLevel);
|
|
321
|
+
const tensDisplay = `[${result.tens.join(",")}]`;
|
|
322
|
+
const unitDisplay = `[${result.unit}]`;
|
|
323
|
+
return `rp ${tensCount}/${skillValue}=${tensDisplay}+${unitDisplay}=${result.diceValue}/${skillValue} ${levelText}
|
|
324
|
+
${response}`;
|
|
325
|
+
} catch (error) {
|
|
326
|
+
return `错误: ${error.message}`;
|
|
327
|
+
}
|
|
328
|
+
});
|
|
329
|
+
ctx.command("添加自定义回复 <level:string> <text:string>", "添加自定义回复(用&分隔多条回复)").alias("添加回复").example("添加自定义回复 大成功 太棒了!大成功!骰值:{result}").example("添加自定义回复 成功 成功!骰值:{result}&干得漂亮!骰值:{result}").action(async ({ session }, level, text) => {
|
|
330
|
+
const validLevels = ["大成功", "极难成功", "困难成功", "成功", "失败", "大失败"];
|
|
331
|
+
if (!validLevels.includes(level)) {
|
|
332
|
+
return `无效的成功等级。可用等级:${validLevels.join("、")}`;
|
|
333
|
+
}
|
|
334
|
+
if (!session?.userId) {
|
|
335
|
+
return "无法获取用户信息,请确保在正确的环境下使用此指令";
|
|
336
|
+
}
|
|
337
|
+
const groupId = session.guildId ? session.guildId : "私聊";
|
|
338
|
+
const replies = text.split("&").map((item) => item.trim()).filter((item) => item.length > 0);
|
|
339
|
+
if (replies.length === 0) {
|
|
340
|
+
return "未提供有效的回复文本";
|
|
341
|
+
}
|
|
342
|
+
const addedResponses = [];
|
|
343
|
+
for (const reply of replies) {
|
|
344
|
+
const result = await ctx.database.create("maple-dice-responses", {
|
|
345
|
+
level,
|
|
346
|
+
content: reply,
|
|
347
|
+
author: session.userId,
|
|
348
|
+
group: groupId,
|
|
349
|
+
created: /* @__PURE__ */ new Date()
|
|
350
|
+
});
|
|
351
|
+
addedResponses.push(result);
|
|
352
|
+
}
|
|
353
|
+
return `成功为"${level}"添加了 ${replies.length} 条自定义回复(群组: ${groupId})
|
|
354
|
+
新增内容:
|
|
355
|
+
${addedResponses.map((r, i) => `${i + 1}. [ID:${r.id}] ${r.content}`).join("\n")}`;
|
|
356
|
+
});
|
|
357
|
+
ctx.command("查看自定义回复 [options]", "查看自定义回复").alias("查看回复").option("mode", "-m 查看由本人添加的所有自定义回复").option("group", "-g 查看当前群组内添加的所有自定义回复(私聊时,仅调用本人私聊添加的所有自定义回复)").option("all", "-a 查看所有自定义回复").example("查看自定义回复 -g 查看当前群组内的自定义回复(默认)").example("查看自定义回复 -m 查看由本人添加的自定义回复").action(async ({ session, options }, level) => {
|
|
358
|
+
let mode = "group";
|
|
359
|
+
if (options?.all) {
|
|
360
|
+
mode = "all";
|
|
361
|
+
} else if (options?.mode) {
|
|
362
|
+
mode = "personal";
|
|
363
|
+
} else if (options?.group) {
|
|
364
|
+
mode = "group";
|
|
365
|
+
}
|
|
366
|
+
const isPrivate = !session?.guildId;
|
|
367
|
+
const userId = session?.userId;
|
|
368
|
+
const groupId = isPrivate ? "私聊" : session?.guildId;
|
|
369
|
+
const query = {};
|
|
370
|
+
if (level) {
|
|
371
|
+
const validLevels = ["大成功", "极难成功", "困难成功", "成功", "失败", "大失败"];
|
|
372
|
+
if (!validLevels.includes(level)) {
|
|
373
|
+
return `无效的成功等级。可用等级:${validLevels.join("、")}`;
|
|
374
|
+
}
|
|
375
|
+
query.level = level;
|
|
376
|
+
}
|
|
377
|
+
switch (mode) {
|
|
378
|
+
case "personal":
|
|
379
|
+
if (!userId) {
|
|
380
|
+
return "无法获取用户信息,请确保在正确的环境下使用此指令";
|
|
381
|
+
}
|
|
382
|
+
query.author = userId;
|
|
383
|
+
break;
|
|
384
|
+
case "group":
|
|
385
|
+
if (!groupId) {
|
|
386
|
+
return "无法获取群组信息,请确保在正确的环境下使用此指令";
|
|
387
|
+
}
|
|
388
|
+
query.group = groupId;
|
|
389
|
+
break;
|
|
390
|
+
case "all":
|
|
391
|
+
break;
|
|
392
|
+
}
|
|
393
|
+
const responses = await ctx.database.get("maple-dice-responses", query);
|
|
394
|
+
if (responses.length === 0) {
|
|
395
|
+
const modeText = {
|
|
396
|
+
"all": "所有",
|
|
397
|
+
"group": `当前${isPrivate ? "私聊" : "群组"}`,
|
|
398
|
+
"personal": "本人"
|
|
399
|
+
}[mode];
|
|
400
|
+
const levelText = level ? `"${level}"` : "";
|
|
401
|
+
return `${modeText}${levelText}暂无自定义回复,请使用"添加自定义回复"指令添加`;
|
|
402
|
+
}
|
|
403
|
+
const grouped = {};
|
|
404
|
+
for (const response of responses) {
|
|
405
|
+
if (!grouped[response.level]) {
|
|
406
|
+
grouped[response.level] = [];
|
|
407
|
+
}
|
|
408
|
+
grouped[response.level].push(response);
|
|
409
|
+
}
|
|
410
|
+
for (const levelName in grouped) {
|
|
411
|
+
grouped[levelName].sort((a, b) => a.id - b.id);
|
|
412
|
+
}
|
|
413
|
+
if (level) {
|
|
414
|
+
const levelResponses = grouped[level] || [];
|
|
415
|
+
const modeText = {
|
|
416
|
+
"all": "所有",
|
|
417
|
+
"group": `当前${isPrivate ? "私聊" : "群组"}`,
|
|
418
|
+
"personal": "本人"
|
|
419
|
+
}[mode];
|
|
420
|
+
let output = `${modeText}"${level}"(${levelResponses.length}条):
|
|
421
|
+
`;
|
|
422
|
+
output += levelResponses.map((r, index) => {
|
|
423
|
+
const isOwner = userId && r.author === userId;
|
|
424
|
+
return `${index + 1}. [ID:${r.id}] ${r.content} ${isOwner ? "(可修改)" : ""}`;
|
|
425
|
+
}).join("\n");
|
|
426
|
+
return output;
|
|
427
|
+
} else {
|
|
428
|
+
const modeText = {
|
|
429
|
+
"all": "所有",
|
|
430
|
+
"group": `当前${isPrivate ? "私聊" : "群组"}`,
|
|
431
|
+
"personal": "本人"
|
|
432
|
+
}[mode];
|
|
433
|
+
let output = `${modeText}自定义回复:
|
|
434
|
+
|
|
435
|
+
`;
|
|
436
|
+
const levelNames = ["大成功", "极难成功", "困难成功", "成功", "失败", "大失败"];
|
|
437
|
+
for (const levelName of levelNames) {
|
|
438
|
+
const levelResponses = grouped[levelName] || [];
|
|
439
|
+
if (levelResponses.length > 0) {
|
|
440
|
+
output += `"${levelName}"(${levelResponses.length}条):
|
|
441
|
+
`;
|
|
442
|
+
output += levelResponses.map((r, index) => {
|
|
443
|
+
const isOwner = userId && r.author === userId;
|
|
444
|
+
return `${index + 1}. [ID:${r.id}] ${r.content} ${isOwner ? "(可修改)" : ""}`;
|
|
445
|
+
}).join("\n");
|
|
446
|
+
output += "\n\n";
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
return output.trim();
|
|
450
|
+
}
|
|
451
|
+
});
|
|
452
|
+
ctx.command("删除自定义回复 <id:number>", '删除自定义回复(ID可从"查看自定义回复 -m"中查看)').alias("删除回复").example("删除自定义回复 1 删除ID为1的回复").action(async ({ session }, id) => {
|
|
453
|
+
if (!session?.userId) {
|
|
454
|
+
return "无法获取用户信息,请确保在正确的环境下使用此指令";
|
|
455
|
+
}
|
|
456
|
+
const existing = await ctx.database.get("maple-dice-responses", { id });
|
|
457
|
+
if (existing.length === 0) {
|
|
458
|
+
return `未找到ID为${id}的回复`;
|
|
459
|
+
}
|
|
460
|
+
const response = existing[0];
|
|
461
|
+
if (response.author !== session.userId) {
|
|
462
|
+
return `无法删除此回复,您只能删除自己添加的回复。
|
|
463
|
+
输入"查看自定义回复 -m"查看由自己添加的回复`;
|
|
464
|
+
}
|
|
465
|
+
const contentToDelete = response.content;
|
|
466
|
+
const level = response.level;
|
|
467
|
+
await ctx.database.remove("maple-dice-responses", { id });
|
|
468
|
+
return `已删除"${level}"的回复(ID: ${id}):
|
|
469
|
+
${contentToDelete}`;
|
|
470
|
+
});
|
|
471
|
+
ctx.command("修改自定义回复 <id:number> <text:string>", '修改自定义回复(ID可从"查看自定义回复 -m"中查看)').alias("修改回复").example("修改自定义回复 1 新的回复内容").action(async ({ session }, id, text) => {
|
|
472
|
+
if (!session?.userId) {
|
|
473
|
+
return "无法获取用户信息,请确保在正确的环境下使用此指令";
|
|
474
|
+
}
|
|
475
|
+
const existing = await ctx.database.get("maple-dice-responses", { id });
|
|
476
|
+
if (existing.length === 0) {
|
|
477
|
+
return `未找到ID为${id}的回复`;
|
|
478
|
+
}
|
|
479
|
+
const response = existing[0];
|
|
480
|
+
if (response.author !== session.userId) {
|
|
481
|
+
return `无法修改此回复,您只能修改自己添加的回复。
|
|
482
|
+
输入"查看自定义回复 -m"查看由自己添加的回复`;
|
|
483
|
+
}
|
|
484
|
+
if (!text.trim()) {
|
|
485
|
+
return "新回复内容不能为空";
|
|
486
|
+
}
|
|
487
|
+
const oldContent = response.content;
|
|
488
|
+
const level = response.level;
|
|
489
|
+
await ctx.database.set("maple-dice-responses", { id }, {
|
|
490
|
+
content: text.trim(),
|
|
491
|
+
created: /* @__PURE__ */ new Date()
|
|
492
|
+
// 更新修改时间
|
|
606
493
|
});
|
|
494
|
+
return `已修改"${level}"的回复(ID: ${id}):
|
|
495
|
+
原内容: ${oldContent}
|
|
496
|
+
新内容: ${text.trim()}`;
|
|
497
|
+
});
|
|
498
|
+
ctx.command("清空自定义回复 [options]", "清空自定义回复").alias("清空回复").option("all", "-a 清空所有自定义回复(默认)").option("me", "-m 清空自己添加的自定义回复").option("user", "-u <userId:string> 清空指定用户添加的所有自定义回复").option("thisGroup", "-tg 清空当前群聊的自定义回复").option("group", "-g <groupId:string> 清空指定群内的所有自定义回复").action(async ({ session, options }) => {
|
|
499
|
+
const userId = session?.userId;
|
|
500
|
+
const groupId = session?.guildId || "私聊";
|
|
501
|
+
const authorOptions = [];
|
|
502
|
+
if (options?.all) authorOptions.push("-a");
|
|
503
|
+
if (options?.me) authorOptions.push("-m");
|
|
504
|
+
if (options?.user) authorOptions.push("-u");
|
|
505
|
+
if (authorOptions.length > 1) {
|
|
506
|
+
return `选项冲突:${authorOptions.join("、")}不能同时使用,请在[-a、-m、-u]中选择一个`;
|
|
507
|
+
}
|
|
508
|
+
const groupOptions = [];
|
|
509
|
+
if (options?.thisGroup) groupOptions.push("-tg");
|
|
510
|
+
if (options?.group) groupOptions.push("-g");
|
|
511
|
+
if (options?.thisGroup && options?.group) {
|
|
512
|
+
return "选项冲突:-tg和-g不能同时使用,请在[-a、-tg、-g]中选择一个";
|
|
513
|
+
}
|
|
514
|
+
let authorQuery = "all";
|
|
515
|
+
let authorValue = void 0;
|
|
516
|
+
if (options?.all) {
|
|
517
|
+
authorQuery = "all";
|
|
518
|
+
} else if (options?.me) {
|
|
519
|
+
if (!userId) {
|
|
520
|
+
return "无法获取用户信息,请确保在正确的环境下使用此指令";
|
|
521
|
+
}
|
|
522
|
+
authorQuery = "me";
|
|
523
|
+
authorValue = userId;
|
|
524
|
+
} else if (options?.user) {
|
|
525
|
+
authorQuery = "user";
|
|
526
|
+
authorValue = options.user;
|
|
527
|
+
}
|
|
528
|
+
let groupQuery = "all";
|
|
529
|
+
let groupValue = void 0;
|
|
530
|
+
if (options?.all) {
|
|
531
|
+
groupQuery = "all";
|
|
532
|
+
} else if (options?.thisGroup) {
|
|
533
|
+
groupQuery = "thisGroup";
|
|
534
|
+
groupValue = groupId;
|
|
535
|
+
} else if (options?.group) {
|
|
536
|
+
groupQuery = "group";
|
|
537
|
+
groupValue = options.group;
|
|
538
|
+
}
|
|
539
|
+
let query = {};
|
|
540
|
+
let description = "";
|
|
541
|
+
switch (authorQuery) {
|
|
542
|
+
case "all":
|
|
543
|
+
description += "所有用户";
|
|
544
|
+
break;
|
|
545
|
+
case "me":
|
|
546
|
+
query.author = authorValue;
|
|
547
|
+
description += "自己";
|
|
548
|
+
break;
|
|
549
|
+
case "user":
|
|
550
|
+
query.author = authorValue;
|
|
551
|
+
description += `用户 ${authorValue}`;
|
|
552
|
+
break;
|
|
553
|
+
}
|
|
554
|
+
switch (groupQuery) {
|
|
555
|
+
case "all":
|
|
556
|
+
description += "的所有群组";
|
|
557
|
+
break;
|
|
558
|
+
case "thisGroup":
|
|
559
|
+
if (authorQuery === "all") {
|
|
560
|
+
description = `${groupId === "私聊" ? "私聊" : "当前群组"}`;
|
|
561
|
+
} else {
|
|
562
|
+
description += `在${groupId === "私聊" ? "私聊" : "当前群组"}内`;
|
|
563
|
+
}
|
|
564
|
+
query.group = groupValue;
|
|
565
|
+
break;
|
|
566
|
+
case "group":
|
|
567
|
+
if (authorQuery === "all") {
|
|
568
|
+
description = `群组 ${groupValue}`;
|
|
569
|
+
} else {
|
|
570
|
+
description += `在群组 ${groupValue} 内`;
|
|
571
|
+
}
|
|
572
|
+
query.group = groupValue;
|
|
573
|
+
break;
|
|
574
|
+
}
|
|
575
|
+
const responses = await ctx.database.get("maple-dice-responses", query);
|
|
576
|
+
const count = responses.length;
|
|
577
|
+
if (count === 0) {
|
|
578
|
+
return `没有找到符合条件的自定义回复`;
|
|
579
|
+
}
|
|
580
|
+
await ctx.database.remove("maple-dice-responses", query);
|
|
581
|
+
return `已清空 ${count} 条${description}的自定义回复`;
|
|
582
|
+
});
|
|
583
|
+
ctx.on("ready", () => {
|
|
584
|
+
console.log("maple-dice-v2 插件已加载完成");
|
|
585
|
+
ctx.logger("maple-dice-v2").info(`默认技能值: ${config.defaultSkill}`);
|
|
586
|
+
ctx.logger("maple-dice-v2").info(`回复模式: ${config.replyMode}`);
|
|
587
|
+
});
|
|
607
588
|
}
|
|
589
|
+
__name(apply, "apply");
|
|
590
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
591
|
+
0 && (module.exports = {
|
|
592
|
+
Config,
|
|
593
|
+
apply,
|
|
594
|
+
name,
|
|
595
|
+
using
|
|
596
|
+
});
|
package/package.json
CHANGED
package/lib/index.d.ts
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import { Context, Schema } from 'koishi';
|
|
2
|
-
export declare const name = "maple-dice-v2";
|
|
3
|
-
export declare const using: readonly ["database"];
|
|
4
|
-
declare module 'koishi' {
|
|
5
|
-
interface Tables {
|
|
6
|
-
'maple-dice-responses': DiceResponse;
|
|
7
|
-
}
|
|
8
|
-
}
|
|
9
|
-
interface DiceResponse {
|
|
10
|
-
id: number;
|
|
11
|
-
level: string;
|
|
12
|
-
content: string;
|
|
13
|
-
author: string;
|
|
14
|
-
group: string;
|
|
15
|
-
created: Date;
|
|
16
|
-
}
|
|
17
|
-
export interface Config {
|
|
18
|
-
defaultSkill: number;
|
|
19
|
-
replyMode: 'global' | 'group' | 'personal';
|
|
20
|
-
}
|
|
21
|
-
export declare const Config: Schema<Config>;
|
|
22
|
-
export declare function apply(ctx: Context, config: Config): void;
|
|
23
|
-
export {};
|