@hieuzest/koishi-plugin-mahjongpub 0.1.18 → 0.1.20
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 +542 -452
- package/package.json +1 -1
package/lib/index.js
CHANGED
|
@@ -1,460 +1,550 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
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 __commonJS = (cb, mod) => function __require() {
|
|
7
|
+
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
8
|
+
};
|
|
9
|
+
var __export = (target, all) => {
|
|
10
|
+
for (var name in all)
|
|
11
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
12
|
+
};
|
|
13
|
+
var __copyProps = (to, from, except, desc) => {
|
|
14
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
15
|
+
for (let key of __getOwnPropNames(from))
|
|
16
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
17
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
18
|
+
}
|
|
19
|
+
return to;
|
|
20
|
+
};
|
|
21
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
22
|
+
|
|
23
|
+
// src/locales/zh-CN.yml
|
|
24
|
+
var require_zh_CN = __commonJS({
|
|
25
|
+
"src/locales/zh-CN.yml"(exports2, module2) {
|
|
26
|
+
module2.exports = { commands: { "mahjongpub.team.bind": { description: "绑定队伍", messages: { failed: "绑定失败", success: "成功: [{cid}:{tid}] {name}" } }, "mahjongpub.team.unbind": { description: "解除绑定", messages: { notbind: "未绑定", success: "成功" } }, "mahjongpub.team.password": { description: "查看密码", messages: { notbind: "未绑定", output: "密码: {0}" } }, "mahjongpub.team.stats": { description: "查看队伍信息", messages: { notbind: "未绑定", failed: "失败", output: "- [{cid}:{tid}] {name}\n{players.map((p, i) => '' + (i+1) + ': ' + p).join('\\n')}\n" } }, "mahjongpub.team.desc": { description: "队伍简介", messages: { notbind: "未绑定", failed: "失败", output: "- [{cid}:{tid}] {name}\n{description}\n" } }, "mahjongpub.team.logo": { description: "队伍头像", messages: { notbind: "未绑定", failed: "失败" } }, "mahjongpub.team.add": { description: "添加队员", messages: { notbind: "未绑定", failed: "失败", success: "- [{cid}:{tid}] {name}\n{players.map((p, i) => '' + (i+1) + ': ' + p).join('\\n')}\n" } }, "mahjongpub.team.remove": { description: "删除队员", messages: { notbind: "未绑定", failed: "失败", success: "- [{cid}:{tid}] {name}\n{players.map((p, i) => '' + (i+1) + ': ' + p).join('\\n')}\n" } }, "mahjongpub.team.swap": { description: "交换队员", messages: { notbind: "未绑定", failed: "失败", invalid: "参数错误", "wide-range": "范围过大", success: "- [{cid}:{tid}] {name}\n{players.map((p, i) => '' + (i+1) + ': ' + p).join('\\n')}\n" } }, "mahjongpub.contest.bind": { description: "绑定比赛", messages: { failed: "绑定失败", success: "成功: [{cid}] {name}" } }, "mahjongpub.contest.record.get": { description: "查询比赛记录", messages: { failed: "查询失败" } }, "mahjongpub.contest.record.update": { description: "修改比赛记录", messages: { failed: "修改失败" } }, "mahjongpub.database.record.get": { description: "查询比赛记录", messages: { failed: "查询失败" } }, "mahjongpub.database.record.update": { description: "修改比赛记录", messages: { success: "修改成功", failed: "修改失败", unmodified: "未修改" } } } };
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
// src/index.ts
|
|
31
|
+
var src_exports = {};
|
|
32
|
+
__export(src_exports, {
|
|
33
|
+
MahjongPub: () => MahjongPub,
|
|
34
|
+
default: () => src_default
|
|
35
|
+
});
|
|
36
|
+
module.exports = __toCommonJS(src_exports);
|
|
37
|
+
var import_koishi = require("koishi");
|
|
38
|
+
|
|
39
|
+
// src/api.ts
|
|
40
|
+
var TeamAdmin = class {
|
|
41
|
+
constructor(ctx, pw, options) {
|
|
42
|
+
this.pw = pw;
|
|
43
|
+
this.options = options;
|
|
44
|
+
this.http = ctx.http.extend({
|
|
45
|
+
endpoint: options.endpoint
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
static {
|
|
49
|
+
__name(this, "TeamAdmin");
|
|
50
|
+
}
|
|
51
|
+
tid;
|
|
52
|
+
cid;
|
|
53
|
+
name;
|
|
54
|
+
description;
|
|
55
|
+
players;
|
|
56
|
+
img;
|
|
57
|
+
ready;
|
|
58
|
+
http;
|
|
59
|
+
async read(force = false) {
|
|
60
|
+
if (this.tid && !force) return;
|
|
61
|
+
const data = await this.http.get("/api/data.php", {
|
|
62
|
+
responseType: "json",
|
|
63
|
+
params: {
|
|
64
|
+
t: "tm_pw",
|
|
65
|
+
cid: this.pw
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
if (!data?.tid) throw new Error("failed to read team info");
|
|
69
|
+
this.tid = data.tid;
|
|
70
|
+
this.cid = data.cid;
|
|
71
|
+
this.name = data.t_name;
|
|
72
|
+
this.description = data.t_ps;
|
|
73
|
+
this.players = [...data.t_player?.split(/\s+/) ?? [], ...data.t_sub?.split(/\s+/) ?? []];
|
|
74
|
+
this.img = data.img;
|
|
75
|
+
this.ready = !!+(data.t_type ?? 0);
|
|
76
|
+
}
|
|
77
|
+
async write() {
|
|
78
|
+
const payload = {
|
|
79
|
+
posttype: "update",
|
|
80
|
+
t_pw: this.pw,
|
|
81
|
+
t_ps: this.description,
|
|
82
|
+
cid: this.cid,
|
|
83
|
+
linkurl: this.img,
|
|
84
|
+
team_type: this.ready ? "1" : "0",
|
|
85
|
+
postdata: this.players.join("\n")
|
|
86
|
+
};
|
|
87
|
+
const form = new FormData();
|
|
88
|
+
Object.entries(payload).forEach(([key, value]) => form.append(key, value));
|
|
89
|
+
return (await this.http.post("/team_post.php", form, { responseType: "json" }))?.msg;
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
var ContestAdmin = class {
|
|
93
|
+
constructor(ctx, cid, pw, options) {
|
|
94
|
+
this.cid = cid;
|
|
95
|
+
this.pw = pw;
|
|
96
|
+
this.options = options;
|
|
97
|
+
this.http = ctx.http.extend({
|
|
98
|
+
endpoint: options.endpoint
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
static {
|
|
102
|
+
__name(this, "ContestAdmin");
|
|
103
|
+
}
|
|
104
|
+
name;
|
|
105
|
+
teams;
|
|
106
|
+
http;
|
|
107
|
+
raw;
|
|
108
|
+
async read(force = false) {
|
|
109
|
+
if (this.teams && !force) return;
|
|
110
|
+
const payload = {
|
|
111
|
+
posttype: "login",
|
|
112
|
+
cid: this.cid,
|
|
113
|
+
c_pw: this.pw
|
|
114
|
+
};
|
|
115
|
+
const form = new FormData();
|
|
116
|
+
Object.entries(payload).forEach(([key, value]) => form.append(key, value));
|
|
117
|
+
const data = await this.http.post("/api/admin_post.php", form, {
|
|
118
|
+
responseType: "json"
|
|
119
|
+
});
|
|
120
|
+
if (!data?.c_admin?.cid) throw new Error("failed to read contest info");
|
|
121
|
+
this.raw = data;
|
|
122
|
+
this.name = data.c_admin.c_name;
|
|
123
|
+
this.teams = Object.fromEntries(data.c_team.map((team) => [team.tid, {
|
|
124
|
+
tid: team.tid,
|
|
125
|
+
cid: this.cid,
|
|
126
|
+
name: team.t_name,
|
|
127
|
+
qq: team.qq.split(/\s+/),
|
|
128
|
+
players: [...team.t_player?.split(/\s+/) ?? [], ...team.t_sub?.split(/\s+/) ?? []],
|
|
129
|
+
pw: team.t_pw
|
|
130
|
+
}]));
|
|
131
|
+
}
|
|
132
|
+
async getRoundRecord(round, cls) {
|
|
133
|
+
const payload = {
|
|
134
|
+
type: "login",
|
|
135
|
+
cid: this.cid,
|
|
136
|
+
cls: String(cls),
|
|
137
|
+
rnd: String(round)
|
|
138
|
+
};
|
|
139
|
+
const form = new FormData();
|
|
140
|
+
Object.entries(payload).forEach(([key, value]) => form.append(key, value));
|
|
141
|
+
const data = await this.http.post("/edit_class_json.php", form, {
|
|
142
|
+
responseType: "json"
|
|
143
|
+
});
|
|
144
|
+
if (data.status !== "2") throw new Error(`failed to get round record with status ${data.status}`);
|
|
145
|
+
const record = {
|
|
146
|
+
cid: this.cid,
|
|
147
|
+
cls,
|
|
148
|
+
rnd: round,
|
|
149
|
+
matches: data.data.map((x) => {
|
|
150
|
+
const players = [];
|
|
151
|
+
for (let i = 0; i < x.length - 1; i += 3) {
|
|
152
|
+
players.push({
|
|
153
|
+
name: x[i],
|
|
154
|
+
point: +x[i + 1],
|
|
155
|
+
score: +x[i + 2]
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
return {
|
|
159
|
+
players,
|
|
160
|
+
logurl: x[x.length - 1]
|
|
161
|
+
};
|
|
162
|
+
})
|
|
163
|
+
};
|
|
164
|
+
return record;
|
|
165
|
+
}
|
|
166
|
+
async updateRoundRecord(record) {
|
|
167
|
+
const payload = {
|
|
168
|
+
type: "update",
|
|
169
|
+
cid: this.cid,
|
|
170
|
+
cls: String(record.cls),
|
|
171
|
+
rnd: String(record.rnd),
|
|
172
|
+
pw: this.pw
|
|
173
|
+
};
|
|
174
|
+
const form = new FormData();
|
|
175
|
+
Object.entries(payload).forEach(([key, value]) => form.append(key, value));
|
|
176
|
+
record.matches.forEach((match) => {
|
|
177
|
+
match.players.forEach((player, i) => {
|
|
178
|
+
form.append(`name${i + 1}[]`, player.name);
|
|
179
|
+
form.append(`point${i + 1}[]`, String(player.point));
|
|
180
|
+
form.append(`score${i + 1}[]`, String(player.score));
|
|
181
|
+
});
|
|
182
|
+
form.append(`logurl[]`, match.logurl);
|
|
183
|
+
});
|
|
184
|
+
const data = await this.http.post("/edit_class_json.php", form, {
|
|
185
|
+
responseType: "json"
|
|
186
|
+
});
|
|
187
|
+
if (data.status !== "2") throw new Error(`failed to update round record with status ${data.status}`);
|
|
188
|
+
return data.data;
|
|
189
|
+
}
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
// src/index.ts
|
|
6
193
|
function parsePlatform(target) {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
194
|
+
const index = target.startsWith("sandbox:") ? target.lastIndexOf(":") : target.indexOf(":");
|
|
195
|
+
const platform = target.slice(0, index);
|
|
196
|
+
const id = target.slice(index + 1);
|
|
197
|
+
return [platform, id];
|
|
11
198
|
}
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
.
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
: session.isDirect ? session.user['mahjongpub/bind-team'] : session.channel['mahjongpub/bind-team'] ?? session.user['mahjongpub/bind-team'];
|
|
167
|
-
if (options.team) {
|
|
168
|
-
const [cid, cpw] = [session.channel['mahjongpub/bind-contest'], session.channel['mahjongpub/bind-contestpw']];
|
|
169
|
-
if (!cid || !cpw)
|
|
170
|
-
return session.text('.notbind');
|
|
171
|
-
const contest = await this.getContest(cid, cpw);
|
|
172
|
-
await contest.read();
|
|
173
|
-
pw = (contest.teams[options.team] ?? Object.values(contest.teams).find(t => t.name === options.team))?.pw;
|
|
174
|
-
}
|
|
175
|
-
if (!pw)
|
|
176
|
-
return config.informNotbind ? session.text('.notbind') : '';
|
|
177
|
-
const team = await this.getTeam(pw);
|
|
178
|
-
try {
|
|
179
|
-
await team.read();
|
|
180
|
-
team.players.push(...users);
|
|
181
|
-
const msg = await team.write();
|
|
182
|
-
await team.read(true);
|
|
183
|
-
return msg + '\n' + session.text('.success', team);
|
|
184
|
-
}
|
|
185
|
-
catch (e) {
|
|
186
|
-
ctx.logger.warn(e);
|
|
187
|
-
return session.text('.failed');
|
|
188
|
-
}
|
|
189
|
-
});
|
|
190
|
-
ctx.command('mahjongpub.team.remove <...indices:natural>', { authority: 3 })
|
|
191
|
-
.alias('!删除', '!删除')
|
|
192
|
-
.option('channel', '-c <channel:channel>')
|
|
193
|
-
.option('team', '-t <team:string>')
|
|
194
|
-
.userFields(['mahjongpub/bind-team', 'mahjongpub/bind-teams'])
|
|
195
|
-
.channelFields(['mahjongpub/bind-team', 'mahjongpub/bind-contest', 'mahjongpub/bind-contestpw'])
|
|
196
|
-
.action(async ({ session, options }, ...indices) => {
|
|
197
|
-
let pw = options.channel ? (await session.getChannel(parsePlatform(options.channel)[1], ['mahjongpub/bind-team']))['mahjongpub/bind-team']
|
|
198
|
-
: session.isDirect ? session.user['mahjongpub/bind-team'] : session.channel['mahjongpub/bind-team'] ?? session.user['mahjongpub/bind-team'];
|
|
199
|
-
if (options.team) {
|
|
200
|
-
const [cid, cpw] = [session.channel['mahjongpub/bind-contest'], session.channel['mahjongpub/bind-contestpw']];
|
|
201
|
-
if (!cid || !cpw)
|
|
202
|
-
return session.text('.notbind');
|
|
203
|
-
const contest = await this.getContest(cid, cpw);
|
|
204
|
-
await contest.read();
|
|
205
|
-
pw = (contest.teams[options.team] ?? Object.values(contest.teams).find(t => t.name === options.team))?.pw;
|
|
206
|
-
}
|
|
207
|
-
if (!pw)
|
|
208
|
-
return config.informNotbind ? session.text('.notbind') : '';
|
|
209
|
-
const team = await this.getTeam(pw);
|
|
210
|
-
try {
|
|
211
|
-
await team.read();
|
|
212
|
-
team.players = team.players.filter((_, i) => !indices.includes(i + 1));
|
|
213
|
-
await team.write();
|
|
214
|
-
const msg = await team.write();
|
|
215
|
-
await team.read(true);
|
|
216
|
-
return msg + '\n' + session.text('.success', team);
|
|
217
|
-
}
|
|
218
|
-
catch (e) {
|
|
219
|
-
ctx.logger.warn(e);
|
|
220
|
-
return session.text('.failed');
|
|
221
|
-
}
|
|
222
|
-
});
|
|
223
|
-
ctx.command('mahjongpub.team.swap <...indices:natural>', { authority: 3 })
|
|
224
|
-
.alias('!交换', '!交换')
|
|
225
|
-
.option('channel', '-c <channel:channel>')
|
|
226
|
-
.option('team', '-t <team:string>')
|
|
227
|
-
.option('start', '-s <start:number>')
|
|
228
|
-
.option('end', '-e <end:number>')
|
|
229
|
-
.option('slim', '--slim')
|
|
230
|
-
.userFields(['mahjongpub/bind-team', 'mahjongpub/bind-teams'])
|
|
231
|
-
.channelFields(['mahjongpub/bind-team', 'mahjongpub/bind-contest', 'mahjongpub/bind-contestpw'])
|
|
232
|
-
.action(async ({ session, options }, ...indices) => {
|
|
233
|
-
let pw = options.channel ? (await session.getChannel(parsePlatform(options.channel)[1], ['mahjongpub/bind-team']))['mahjongpub/bind-team']
|
|
234
|
-
: session.isDirect ? session.user['mahjongpub/bind-team'] : session.channel['mahjongpub/bind-team'] ?? session.user['mahjongpub/bind-team'];
|
|
235
|
-
if (options.team) {
|
|
236
|
-
const [cid, cpw] = [session.channel['mahjongpub/bind-contest'], session.channel['mahjongpub/bind-contestpw']];
|
|
237
|
-
if (!cid || !cpw)
|
|
238
|
-
return session.text('.notbind');
|
|
239
|
-
const contest = await this.getContest(cid, cpw);
|
|
240
|
-
await contest.read();
|
|
241
|
-
pw = (contest.teams[options.team] ?? Object.values(contest.teams).find(t => t.name === options.team))?.pw;
|
|
242
|
-
}
|
|
243
|
-
else if (options.start && options.end) {
|
|
244
|
-
if (options.end - options.start > 100)
|
|
245
|
-
return session.text('.wide-range');
|
|
246
|
-
const msg = [];
|
|
247
|
-
for (let tid = options.start; tid <= options.end; tid++) {
|
|
248
|
-
msg.push(await session.execute({
|
|
249
|
-
name: 'mahjongpub.team.swap',
|
|
250
|
-
args: indices,
|
|
251
|
-
options: {
|
|
252
|
-
channel: options.channel,
|
|
253
|
-
team: `${tid}`,
|
|
254
|
-
slim: true,
|
|
255
|
-
},
|
|
256
|
-
}, true));
|
|
257
|
-
if (msg.length >= config.batchCount)
|
|
258
|
-
await session.send(msg.splice(0).join('\n'));
|
|
259
|
-
await ctx.sleep(config.batchInterval);
|
|
260
|
-
}
|
|
261
|
-
return msg.length ? msg.join('\n') : '';
|
|
262
|
-
}
|
|
263
|
-
if (!pw)
|
|
264
|
-
return config.informNotbind ? session.text('.notbind') : '';
|
|
265
|
-
if (!indices.length || indices.length % 2 !== 0)
|
|
266
|
-
return session.text('.invalid');
|
|
267
|
-
const team = await this.getTeam(pw);
|
|
268
|
-
try {
|
|
269
|
-
await team.read();
|
|
270
|
-
for (let i = 0; i < indices.length; i += 2) {
|
|
271
|
-
const t = team.players[indices[i] - 1];
|
|
272
|
-
team.players[indices[i] - 1] = team.players[indices[i + 1] - 1];
|
|
273
|
-
team.players[indices[i + 1] - 1] = t;
|
|
274
|
-
}
|
|
275
|
-
const msg = await team.write();
|
|
276
|
-
await team.read(true);
|
|
277
|
-
if (options.slim)
|
|
278
|
-
return `[${team.tid} ${team.name}] ${msg} ` + indices.map(i => `${i}. ${team.players[i - 1]}`).join(' ');
|
|
279
|
-
else
|
|
280
|
-
return msg + '\n' + session.text('.success', team);
|
|
281
|
-
}
|
|
282
|
-
catch (e) {
|
|
283
|
-
ctx.logger.warn(e);
|
|
284
|
-
return session.text('.failed');
|
|
285
|
-
}
|
|
286
|
-
});
|
|
287
|
-
ctx.command('mahjongpub.contest.bind <cid:string> <cpw:string>', { authority: 4 })
|
|
288
|
-
.option('channel', '-c <channel:channel>')
|
|
289
|
-
.channelFields(['mahjongpub/bind-contest', 'mahjongpub/bind-contestpw'])
|
|
290
|
-
.action(async ({ session, options }, cid, cpw) => {
|
|
291
|
-
const contest = await this.getContest(cid, cpw);
|
|
292
|
-
try {
|
|
293
|
-
await contest.read();
|
|
294
|
-
}
|
|
295
|
-
catch (e) {
|
|
296
|
-
ctx.logger.warn(e);
|
|
297
|
-
return session.text('.failed');
|
|
298
|
-
}
|
|
299
|
-
if (options.channel) {
|
|
300
|
-
ctx.database.setChannel(...parsePlatform(options.channel), {
|
|
301
|
-
'mahjongpub/bind-contest': cid,
|
|
302
|
-
'mahjongpub/bind-contestpw': cpw,
|
|
303
|
-
});
|
|
304
|
-
}
|
|
305
|
-
else {
|
|
306
|
-
session.channel['mahjongpub/bind-contest'] = cid;
|
|
307
|
-
session.channel['mahjongpub/bind-contestpw'] = cpw;
|
|
308
|
-
}
|
|
309
|
-
return session.text('.success', contest);
|
|
310
|
-
});
|
|
311
|
-
ctx.command('mahjongpub.contest.record.get <round:natural> <cls:natural>', { authority: 3 })
|
|
312
|
-
.option('rowi', '-i <rowi:integer>')
|
|
313
|
-
.channelFields(['mahjongpub/bind-contest', 'mahjongpub/bind-contestpw'])
|
|
314
|
-
.action(async ({ session, options }, round, cls) => {
|
|
315
|
-
const [cid, cpw] = [session.channel['mahjongpub/bind-contest'], session.channel['mahjongpub/bind-contestpw']];
|
|
316
|
-
const contest = await this.getContest(cid, cpw);
|
|
317
|
-
try {
|
|
318
|
-
const record = await contest.getRoundRecord(round, cls);
|
|
319
|
-
if ((0, koishi_1.isNullable)(options.rowi)) {
|
|
320
|
-
return record.matches.map((match, i) => `[${i}] ` + match.players.map(x => `${x.name} ${x.point}`).join(' / ')).join('\n');
|
|
321
|
-
}
|
|
322
|
-
else {
|
|
323
|
-
return [
|
|
324
|
-
`[${options.rowi === -1 ? record.matches.length - 1 : options.rowi}]`,
|
|
325
|
-
record.matches.at(options.rowi ?? -1).players.map(x => `${x.name} ${x.point}`).join(' / '),
|
|
326
|
-
].join(' ');
|
|
327
|
-
}
|
|
328
|
-
}
|
|
329
|
-
catch (e) {
|
|
330
|
-
ctx.logger.warn(e);
|
|
331
|
-
return session.text('.failed');
|
|
199
|
+
__name(parsePlatform, "parsePlatform");
|
|
200
|
+
var MahjongPub = class {
|
|
201
|
+
constructor(ctx, config) {
|
|
202
|
+
this.ctx = ctx;
|
|
203
|
+
this.config = config;
|
|
204
|
+
ctx.i18n.define("zh-CN", require_zh_CN());
|
|
205
|
+
ctx.model.extend("user", {
|
|
206
|
+
"mahjongpub/bind-team": "string",
|
|
207
|
+
"mahjongpub/bind-teams": "json"
|
|
208
|
+
});
|
|
209
|
+
ctx.model.extend("channel", {
|
|
210
|
+
"mahjongpub/bind-team": "string",
|
|
211
|
+
"mahjongpub/bind-contest": "string",
|
|
212
|
+
"mahjongpub/bind-contestpw": "string"
|
|
213
|
+
});
|
|
214
|
+
ctx.command("mahjongpub.team.bind <pw:string>").alias("!绑定", "!绑定").option("user", "-u <user:user>").option("channel", "-c <channel:channel>").userFields(["mahjongpub/bind-team"]).channelFields(["mahjongpub/bind-team"]).action(async ({ session, options }, pw) => {
|
|
215
|
+
if (pw?.length !== 20) return;
|
|
216
|
+
const team = await this.getTeam(pw);
|
|
217
|
+
try {
|
|
218
|
+
await team.read();
|
|
219
|
+
} catch (e) {
|
|
220
|
+
ctx.logger.warn(e);
|
|
221
|
+
return session.text(".failed");
|
|
222
|
+
}
|
|
223
|
+
if (options.user) ctx.database.setUser(...parsePlatform(options.user), { "mahjongpub/bind-team": pw });
|
|
224
|
+
else if (options.channel) ctx.database.setChannel(...parsePlatform(options.channel), { "mahjongpub/bind-team": pw });
|
|
225
|
+
else if (session.isDirect) session.user["mahjongpub/bind-team"] = pw;
|
|
226
|
+
else session.channel["mahjongpub/bind-team"] = pw;
|
|
227
|
+
return session.text(".success", team);
|
|
228
|
+
});
|
|
229
|
+
ctx.command("mahjongpub.team.unbind").alias("!解绑", "!解绑").option("channel", "-c <channel:channel>").userFields(["mahjongpub/bind-team"]).channelFields(["mahjongpub/bind-team"]).action(async ({ session, options }) => {
|
|
230
|
+
const pw = options.channel ? (await session.getChannel(parsePlatform(options.channel)[1], ["mahjongpub/bind-team"]))["mahjongpub/bind-team"] : session.isDirect ? session.user["mahjongpub/bind-team"] : session.channel["mahjongpub/bind-team"] ?? session.user["mahjongpub/bind-team"];
|
|
231
|
+
if (!pw) return config.informNotbind ? session.text(".notbind") : "";
|
|
232
|
+
if (session.isDirect) session.user["mahjongpub/bind-team"] = "";
|
|
233
|
+
else session.channel["mahjongpub/bind-team"] = "";
|
|
234
|
+
return session.text(".success");
|
|
235
|
+
});
|
|
236
|
+
ctx.private().command("mahjongpub.team.password").alias("!密码", "!密码").userFields(["mahjongpub/bind-team"]).action(async ({ session }) => {
|
|
237
|
+
const pw = session.user["mahjongpub/bind-team"];
|
|
238
|
+
if (!pw) return config.informNotbind ? session.text(".notbind") : "";
|
|
239
|
+
return session.text(".output", [pw]);
|
|
240
|
+
});
|
|
241
|
+
ctx.command("mahjongpub.team.stats").alias("!信息", "!信息", "!概况", "!概况").option("channel", "-c <channel:channel>").option("team", "-t <team:string>").userFields(["mahjongpub/bind-team", "mahjongpub/bind-teams"]).channelFields(["mahjongpub/bind-team", "mahjongpub/bind-contest", "mahjongpub/bind-contestpw"]).action(async ({ session, options }) => {
|
|
242
|
+
let pw = options.channel ? (await session.getChannel(parsePlatform(options.channel)[1], ["mahjongpub/bind-team"]))["mahjongpub/bind-team"] : session.isDirect ? session.user["mahjongpub/bind-team"] : session.channel["mahjongpub/bind-team"] ?? session.user["mahjongpub/bind-team"];
|
|
243
|
+
if (options.team) {
|
|
244
|
+
const [cid, cpw] = [session.channel["mahjongpub/bind-contest"], session.channel["mahjongpub/bind-contestpw"]];
|
|
245
|
+
if (!cid || !cpw) return session.text(".notbind");
|
|
246
|
+
const contest = await this.getContest(cid, cpw);
|
|
247
|
+
await contest.read();
|
|
248
|
+
pw = (contest.teams[options.team] ?? Object.values(contest.teams).find((t) => t.name === options.team))?.pw;
|
|
249
|
+
}
|
|
250
|
+
if (!pw) return config.informNotbind ? session.text(".notbind") : "";
|
|
251
|
+
const team = await this.getTeam(pw);
|
|
252
|
+
try {
|
|
253
|
+
await team.read();
|
|
254
|
+
return session.text(".output", team);
|
|
255
|
+
} catch (e) {
|
|
256
|
+
ctx.logger.warn(e);
|
|
257
|
+
return session.text(".failed");
|
|
258
|
+
}
|
|
259
|
+
});
|
|
260
|
+
ctx.command("mahjongpub.team.desc [desc:rawtext]").alias("!简介", "!简介").option("channel", "-c <channel:channel>").userFields(["mahjongpub/bind-team"]).channelFields(["mahjongpub/bind-team"]).action(async ({ session, options }, desc) => {
|
|
261
|
+
const pw = options.channel ? (await session.getChannel(parsePlatform(options.channel)[1], ["mahjongpub/bind-team"]))["mahjongpub/bind-team"] : session.isDirect ? session.user["mahjongpub/bind-team"] : session.channel["mahjongpub/bind-team"] ?? session.user["mahjongpub/bind-team"];
|
|
262
|
+
if (!pw) return config.informNotbind ? session.text(".notbind") : "";
|
|
263
|
+
const team = await this.getTeam(pw);
|
|
264
|
+
try {
|
|
265
|
+
await team.read();
|
|
266
|
+
if (!desc) return session.text(".output", team);
|
|
267
|
+
team.description = desc;
|
|
268
|
+
return await team.write();
|
|
269
|
+
} catch (e) {
|
|
270
|
+
ctx.logger.warn(e);
|
|
271
|
+
return session.text(".failed");
|
|
272
|
+
}
|
|
273
|
+
});
|
|
274
|
+
ctx.command("mahjongpub.team.logo [img:img]").alias("!头像", "!头像").option("channel", "-c <channel:channel>").userFields(["mahjongpub/bind-team"]).channelFields(["mahjongpub/bind-team"]).action(async ({ session, options }, img) => {
|
|
275
|
+
const pw = options.channel ? (await session.getChannel(parsePlatform(options.channel)[1], ["mahjongpub/bind-team"]))["mahjongpub/bind-team"] : session.isDirect ? session.user["mahjongpub/bind-team"] : session.channel["mahjongpub/bind-team"] ?? session.user["mahjongpub/bind-team"];
|
|
276
|
+
if (!pw) return config.informNotbind ? session.text(".notbind") : "";
|
|
277
|
+
const team = await this.getTeam(pw);
|
|
278
|
+
try {
|
|
279
|
+
await team.read();
|
|
280
|
+
if (!img) return import_koishi.h.image(team.img);
|
|
281
|
+
const url = await ctx.assets.upload("https://koishi.chat/logo.png", `${session.id}-${session.timestamp}.png`);
|
|
282
|
+
team.img = url;
|
|
283
|
+
return await team.write();
|
|
284
|
+
} catch (e) {
|
|
285
|
+
ctx.logger.warn(e);
|
|
286
|
+
return session.text(".failed");
|
|
287
|
+
}
|
|
288
|
+
});
|
|
289
|
+
ctx.command("mahjongpub.team.add <...users:string>", { authority: 3 }).alias("!添加", "!添加").option("channel", "-c <channel:channel>").option("team", "-t <team:string>").userFields(["mahjongpub/bind-team", "mahjongpub/bind-teams"]).channelFields(["mahjongpub/bind-team", "mahjongpub/bind-contest", "mahjongpub/bind-contestpw"]).action(async ({ session, options }, ...users) => {
|
|
290
|
+
let pw = options.channel ? (await session.getChannel(parsePlatform(options.channel)[1], ["mahjongpub/bind-team"]))["mahjongpub/bind-team"] : session.isDirect ? session.user["mahjongpub/bind-team"] : session.channel["mahjongpub/bind-team"] ?? session.user["mahjongpub/bind-team"];
|
|
291
|
+
if (options.team) {
|
|
292
|
+
const [cid, cpw] = [session.channel["mahjongpub/bind-contest"], session.channel["mahjongpub/bind-contestpw"]];
|
|
293
|
+
if (!cid || !cpw) return session.text(".notbind");
|
|
294
|
+
const contest = await this.getContest(cid, cpw);
|
|
295
|
+
await contest.read();
|
|
296
|
+
pw = (contest.teams[options.team] ?? Object.values(contest.teams).find((t) => t.name === options.team))?.pw;
|
|
297
|
+
}
|
|
298
|
+
if (!pw) return config.informNotbind ? session.text(".notbind") : "";
|
|
299
|
+
const team = await this.getTeam(pw);
|
|
300
|
+
try {
|
|
301
|
+
await team.read();
|
|
302
|
+
team.players.push(...users);
|
|
303
|
+
const msg = await team.write();
|
|
304
|
+
await team.read(true);
|
|
305
|
+
return msg + "\n" + session.text(".success", team);
|
|
306
|
+
} catch (e) {
|
|
307
|
+
ctx.logger.warn(e);
|
|
308
|
+
return session.text(".failed");
|
|
309
|
+
}
|
|
310
|
+
});
|
|
311
|
+
ctx.command("mahjongpub.team.remove <...indices:natural>", { authority: 3 }).alias("!删除", "!删除").option("channel", "-c <channel:channel>").option("team", "-t <team:string>").userFields(["mahjongpub/bind-team", "mahjongpub/bind-teams"]).channelFields(["mahjongpub/bind-team", "mahjongpub/bind-contest", "mahjongpub/bind-contestpw"]).action(async ({ session, options }, ...indices) => {
|
|
312
|
+
let pw = options.channel ? (await session.getChannel(parsePlatform(options.channel)[1], ["mahjongpub/bind-team"]))["mahjongpub/bind-team"] : session.isDirect ? session.user["mahjongpub/bind-team"] : session.channel["mahjongpub/bind-team"] ?? session.user["mahjongpub/bind-team"];
|
|
313
|
+
if (options.team) {
|
|
314
|
+
const [cid, cpw] = [session.channel["mahjongpub/bind-contest"], session.channel["mahjongpub/bind-contestpw"]];
|
|
315
|
+
if (!cid || !cpw) return session.text(".notbind");
|
|
316
|
+
const contest = await this.getContest(cid, cpw);
|
|
317
|
+
await contest.read();
|
|
318
|
+
pw = (contest.teams[options.team] ?? Object.values(contest.teams).find((t) => t.name === options.team))?.pw;
|
|
319
|
+
}
|
|
320
|
+
if (!pw) return config.informNotbind ? session.text(".notbind") : "";
|
|
321
|
+
const team = await this.getTeam(pw);
|
|
322
|
+
try {
|
|
323
|
+
await team.read();
|
|
324
|
+
team.players = team.players.filter((_, i) => !indices.includes(i + 1));
|
|
325
|
+
await team.write();
|
|
326
|
+
const msg = await team.write();
|
|
327
|
+
await team.read(true);
|
|
328
|
+
return msg + "\n" + session.text(".success", team);
|
|
329
|
+
} catch (e) {
|
|
330
|
+
ctx.logger.warn(e);
|
|
331
|
+
return session.text(".failed");
|
|
332
|
+
}
|
|
333
|
+
});
|
|
334
|
+
ctx.command("mahjongpub.team.swap <...indices:natural>", { authority: 3 }).alias("!交换", "!交换").option("channel", "-c <channel:channel>").option("team", "-t <team:string>").option("start", "-s <start:number>").option("end", "-e <end:number>").option("slim", "--slim").userFields(["mahjongpub/bind-team", "mahjongpub/bind-teams"]).channelFields(["mahjongpub/bind-team", "mahjongpub/bind-contest", "mahjongpub/bind-contestpw"]).action(async ({ session, options }, ...indices) => {
|
|
335
|
+
let pw = options.channel ? (await session.getChannel(parsePlatform(options.channel)[1], ["mahjongpub/bind-team"]))["mahjongpub/bind-team"] : session.isDirect ? session.user["mahjongpub/bind-team"] : session.channel["mahjongpub/bind-team"] ?? session.user["mahjongpub/bind-team"];
|
|
336
|
+
if (options.team) {
|
|
337
|
+
const [cid, cpw] = [session.channel["mahjongpub/bind-contest"], session.channel["mahjongpub/bind-contestpw"]];
|
|
338
|
+
if (!cid || !cpw) return session.text(".notbind");
|
|
339
|
+
const contest = await this.getContest(cid, cpw);
|
|
340
|
+
await contest.read();
|
|
341
|
+
pw = (contest.teams[options.team] ?? Object.values(contest.teams).find((t) => t.name === options.team))?.pw;
|
|
342
|
+
} else if (options.start && options.end) {
|
|
343
|
+
if (options.end - options.start > 100) return session.text(".wide-range");
|
|
344
|
+
const msg = [];
|
|
345
|
+
for (let tid = options.start; tid <= options.end; tid++) {
|
|
346
|
+
msg.push(await session.execute({
|
|
347
|
+
name: "mahjongpub.team.swap",
|
|
348
|
+
args: indices,
|
|
349
|
+
options: {
|
|
350
|
+
channel: options.channel,
|
|
351
|
+
team: `${tid}`,
|
|
352
|
+
slim: true
|
|
332
353
|
}
|
|
354
|
+
}, true));
|
|
355
|
+
if (msg.length >= config.batchCount) await session.send(msg.splice(0).join("\n"));
|
|
356
|
+
await ctx.sleep(config.batchInterval);
|
|
357
|
+
}
|
|
358
|
+
return msg.length ? msg.join("\n") : "";
|
|
359
|
+
}
|
|
360
|
+
if (!pw) return config.informNotbind ? session.text(".notbind") : "";
|
|
361
|
+
if (!indices.length || indices.length % 2 !== 0) return session.text(".invalid");
|
|
362
|
+
const team = await this.getTeam(pw);
|
|
363
|
+
try {
|
|
364
|
+
await team.read();
|
|
365
|
+
for (let i = 0; i < indices.length; i += 2) {
|
|
366
|
+
const t = team.players[indices[i] - 1];
|
|
367
|
+
team.players[indices[i] - 1] = team.players[indices[i + 1] - 1];
|
|
368
|
+
team.players[indices[i + 1] - 1] = t;
|
|
369
|
+
}
|
|
370
|
+
const msg = await team.write();
|
|
371
|
+
await team.read(true);
|
|
372
|
+
if (options.slim) return `[${team.tid} ${team.name}] ${msg} ` + indices.map((i) => `${i}. ${team.players[i - 1]}`).join(" ");
|
|
373
|
+
else return msg + "\n" + session.text(".success", team);
|
|
374
|
+
} catch (e) {
|
|
375
|
+
ctx.logger.warn(e);
|
|
376
|
+
return session.text(".failed");
|
|
377
|
+
}
|
|
378
|
+
});
|
|
379
|
+
ctx.command("mahjongpub.contest.bind <cid:string> <cpw:string>", { authority: 4 }).option("channel", "-c <channel:channel>").channelFields(["mahjongpub/bind-contest", "mahjongpub/bind-contestpw"]).action(async ({ session, options }, cid, cpw) => {
|
|
380
|
+
const contest = await this.getContest(cid, cpw);
|
|
381
|
+
try {
|
|
382
|
+
await contest.read();
|
|
383
|
+
} catch (e) {
|
|
384
|
+
ctx.logger.warn(e);
|
|
385
|
+
return session.text(".failed");
|
|
386
|
+
}
|
|
387
|
+
if (options.channel) {
|
|
388
|
+
ctx.database.setChannel(...parsePlatform(options.channel), {
|
|
389
|
+
"mahjongpub/bind-contest": cid,
|
|
390
|
+
"mahjongpub/bind-contestpw": cpw
|
|
333
391
|
});
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
392
|
+
} else {
|
|
393
|
+
session.channel["mahjongpub/bind-contest"] = cid;
|
|
394
|
+
session.channel["mahjongpub/bind-contestpw"] = cpw;
|
|
395
|
+
}
|
|
396
|
+
return session.text(".success", contest);
|
|
397
|
+
});
|
|
398
|
+
ctx.command("mahjongpub.contest.record.get <round:natural> <cls:natural>", { authority: 3 }).option("rowi", "-i <rowi:integer>").channelFields(["mahjongpub/bind-contest", "mahjongpub/bind-contestpw"]).action(async ({ session, options }, round, cls) => {
|
|
399
|
+
const [cid, cpw] = [session.channel["mahjongpub/bind-contest"], session.channel["mahjongpub/bind-contestpw"]];
|
|
400
|
+
const contest = await this.getContest(cid, cpw);
|
|
401
|
+
try {
|
|
402
|
+
const record = await contest.getRoundRecord(round, cls);
|
|
403
|
+
if ((0, import_koishi.isNullable)(options.rowi)) {
|
|
404
|
+
return record.matches.map((match, i) => `[${i}] ` + match.players.map((x) => `${x.name} ${x.point}`).join(" / ")).join("\n");
|
|
405
|
+
} else {
|
|
406
|
+
return [
|
|
407
|
+
`[${options.rowi === -1 ? record.matches.length - 1 : options.rowi}]`,
|
|
408
|
+
record.matches.at(options.rowi ?? -1).players.map((x) => `${x.name} ${x.point}`).join(" / ")
|
|
409
|
+
].join(" ");
|
|
410
|
+
}
|
|
411
|
+
} catch (e) {
|
|
412
|
+
ctx.logger.warn(e);
|
|
413
|
+
return session.text(".failed");
|
|
414
|
+
}
|
|
415
|
+
});
|
|
416
|
+
ctx.command("mahjongpub.contest.record.update <round:natural> <cls:natural> <...points:integer>", { authority: 3 }).option("rowi", "-i <rowi:integer>", { fallback: -1 }).channelFields(["mahjongpub/bind-contest", "mahjongpub/bind-contestpw"]).action(async ({ session, options }, round, cls, ...points) => {
|
|
417
|
+
const [cid, cpw] = [session.channel["mahjongpub/bind-contest"], session.channel["mahjongpub/bind-contestpw"]];
|
|
418
|
+
const contest = await this.getContest(cid, cpw);
|
|
419
|
+
try {
|
|
420
|
+
await contest.read();
|
|
421
|
+
const record = await contest.getRoundRecord(round, cls);
|
|
422
|
+
record.matches.at(options.rowi).players.forEach((x, i) => {
|
|
423
|
+
x.point = points[i];
|
|
424
|
+
x.score = x.point - (options.rowi === 0 ? +contest.raw.c_admin.c_s_po : record.matches.at(options.rowi - 1).players[i].point);
|
|
353
425
|
});
|
|
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
|
-
ctx.command('mahjongpub.database.record.update <round:natural> <cls:natural> <...points:integer>', { authority: 4 })
|
|
379
|
-
.option('rowi', '-i <rowi:integer>', { fallback: 9 })
|
|
380
|
-
.option('ver', '-v <ver:integer>', { fallback: 0 })
|
|
381
|
-
.channelFields(['mahjongpub/bind-contest'])
|
|
382
|
-
.action(async ({ session, options }, round, cls, ...points) => {
|
|
383
|
-
const [cid] = [session.channel['mahjongpub/bind-contest']];
|
|
384
|
-
try {
|
|
385
|
-
const res = await ctx.mahjong.database.db('scoreboard').collection('matches').updateOne({
|
|
386
|
-
cid,
|
|
387
|
-
cls,
|
|
388
|
-
round,
|
|
389
|
-
rowi: options.rowi,
|
|
390
|
-
ver: options.ver,
|
|
391
|
-
}, {
|
|
392
|
-
$set: Object.fromEntries(points.map((p, i) => [`results.${i}.num`, p])),
|
|
393
|
-
});
|
|
394
|
-
return res.modifiedCount ? session.text('.success') : res.matchedCount ? session.text('.unmodified') : session.text('.failed');
|
|
395
|
-
}
|
|
396
|
-
catch (e) {
|
|
397
|
-
ctx.logger.warn(e);
|
|
398
|
-
return session.text('.failed');
|
|
399
|
-
}
|
|
400
|
-
});
|
|
401
|
-
ctx.command('mahjongpub.admin.record.get <round:natural> <cls:natural>', { authority: 3 })
|
|
402
|
-
.option('rowi', '-i <rowi:integer>', { fallback: 9 })
|
|
403
|
-
.option('ver', '-v <ver:integer>', { fallback: 0 })
|
|
404
|
-
.action(async ({ session, options }, round, cls) => {
|
|
405
|
-
const msg = [];
|
|
406
|
-
msg.push('- Mahjongpub');
|
|
407
|
-
msg.push(await session.execute({
|
|
408
|
-
name: 'mahjongpub.contest.record.get',
|
|
409
|
-
args: [round, cls],
|
|
410
|
-
options,
|
|
411
|
-
}, true));
|
|
412
|
-
msg.push('- Database');
|
|
413
|
-
msg.push(await session.execute({
|
|
414
|
-
name: 'mahjongpub.database.record.get',
|
|
415
|
-
args: [round, cls],
|
|
416
|
-
options,
|
|
417
|
-
}, true));
|
|
418
|
-
return msg.join('\n');
|
|
419
|
-
});
|
|
426
|
+
return await contest.updateRoundRecord(record);
|
|
427
|
+
} catch (e) {
|
|
428
|
+
ctx.logger.warn(e);
|
|
429
|
+
return session.text(".failed");
|
|
430
|
+
}
|
|
431
|
+
});
|
|
432
|
+
if (ctx.get("mahjong.database")) {
|
|
433
|
+
ctx.command("mahjongpub.database.record.get <round:natural> <cls:natural>", { authority: 3 }).option("rowi", "-i <rowi:integer>", { fallback: -1 }).option("ver", "-v <ver:integer>", { fallback: 0 }).channelFields(["mahjongpub/bind-contest"]).action(async ({ session, options }, round, cls) => {
|
|
434
|
+
const [cid] = [session.channel["mahjongpub/bind-contest"]];
|
|
435
|
+
try {
|
|
436
|
+
const record = await ctx.mahjong.database.db("scoreboard").collection("matches").find({
|
|
437
|
+
cid,
|
|
438
|
+
cls,
|
|
439
|
+
round,
|
|
440
|
+
ver: options.ver,
|
|
441
|
+
...options.rowi === -1 ? {} : { rowi: options.rowi }
|
|
442
|
+
}).sort({ rowi: -1 }).toArray();
|
|
443
|
+
if (!record.length) return session.text(".failed");
|
|
444
|
+
return record.map((r) => `[${r.rowi}] ` + r.results.map((x) => `${x.name} ${x.num}`).join(" / ")).join("\n");
|
|
445
|
+
} catch (e) {
|
|
446
|
+
ctx.logger.warn(e);
|
|
447
|
+
return session.text(".failed");
|
|
420
448
|
}
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
await res.read();
|
|
439
|
-
await this.ctx.cache.set('contests', cid, res, 1000 * 600);
|
|
440
|
-
return res;
|
|
449
|
+
});
|
|
450
|
+
ctx.command("mahjongpub.database.record.update <round:natural> <cls:natural> <...points:integer>", { authority: 4 }).option("rowi", "-i <rowi:integer>", { fallback: 9 }).option("ver", "-v <ver:integer>", { fallback: 0 }).channelFields(["mahjongpub/bind-contest"]).action(async ({ session, options }, round, cls, ...points) => {
|
|
451
|
+
const [cid] = [session.channel["mahjongpub/bind-contest"]];
|
|
452
|
+
try {
|
|
453
|
+
const res = await ctx.mahjong.database.db("scoreboard").collection("matches").updateOne({
|
|
454
|
+
cid,
|
|
455
|
+
cls,
|
|
456
|
+
round,
|
|
457
|
+
rowi: options.rowi,
|
|
458
|
+
ver: options.ver
|
|
459
|
+
}, {
|
|
460
|
+
$set: Object.fromEntries(points.map((p, i) => [`results.${i}.num`, p]))
|
|
461
|
+
});
|
|
462
|
+
return res.modifiedCount ? session.text(".success") : res.matchedCount ? session.text(".unmodified") : session.text(".failed");
|
|
463
|
+
} catch (e) {
|
|
464
|
+
ctx.logger.warn(e);
|
|
465
|
+
return session.text(".failed");
|
|
441
466
|
}
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
467
|
+
});
|
|
468
|
+
ctx.command("mahjongpub.admin.record.get <round:natural> <cls:natural>", { authority: 3 }).option("rowi", "-i <rowi:integer>", { fallback: 9 }).option("ver", "-v <ver:integer>", { fallback: 0 }).action(async ({ session, options }, round, cls) => {
|
|
469
|
+
const msg = [];
|
|
470
|
+
msg.push("- Mahjongpub");
|
|
471
|
+
msg.push(await session.execute({
|
|
472
|
+
name: "mahjongpub.contest.record.get",
|
|
473
|
+
args: [round, cls],
|
|
474
|
+
options
|
|
475
|
+
}, true));
|
|
476
|
+
msg.push("- Database");
|
|
477
|
+
msg.push(await session.execute({
|
|
478
|
+
name: "mahjongpub.database.record.get",
|
|
479
|
+
args: [round, cls],
|
|
480
|
+
options
|
|
481
|
+
}, true));
|
|
482
|
+
return msg.join("\n");
|
|
483
|
+
});
|
|
484
|
+
ctx.command("mahjongpub.admin.record.update <round:natural> <cls:natural> <...points:integer>", { authority: 4 }).option("rowi", "-i <rowi:integer>", { fallback: 9 }).option("ver", "-v <ver:integer>", { fallback: 0 }).action(async ({ session, options }, round, cls, ...points) => {
|
|
485
|
+
const msg = [];
|
|
486
|
+
msg.push("- Mahjongpub");
|
|
487
|
+
msg.push(await session.execute({
|
|
488
|
+
name: "mahjongpub.contest.record.update",
|
|
489
|
+
args: [round, cls, ...points],
|
|
490
|
+
options
|
|
491
|
+
}, true));
|
|
492
|
+
msg.push(await session.execute({
|
|
493
|
+
name: "mahjongpub.contest.record.update",
|
|
494
|
+
args: [round, cls, ...points],
|
|
495
|
+
options
|
|
496
|
+
}, true));
|
|
497
|
+
msg.push("- Database");
|
|
498
|
+
msg.push(await session.execute({
|
|
499
|
+
name: "mahjongpub.database.record.get",
|
|
500
|
+
args: [round, cls, ...points],
|
|
501
|
+
options
|
|
502
|
+
}, true));
|
|
503
|
+
msg.push(await session.execute({
|
|
504
|
+
name: "mahjongpub.database.record.get",
|
|
505
|
+
args: [round, cls, ...points],
|
|
506
|
+
options
|
|
507
|
+
}, true));
|
|
508
|
+
return msg.join("\n");
|
|
509
|
+
});
|
|
445
510
|
}
|
|
446
|
-
}
|
|
447
|
-
|
|
448
|
-
(
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
511
|
+
}
|
|
512
|
+
static {
|
|
513
|
+
__name(this, "MahjongPub");
|
|
514
|
+
}
|
|
515
|
+
teams = {};
|
|
516
|
+
contests = {};
|
|
517
|
+
async getTeam(pw) {
|
|
518
|
+
return new TeamAdmin(this.ctx, pw, this.config);
|
|
519
|
+
}
|
|
520
|
+
async getContest(cid, pw) {
|
|
521
|
+
if (this.ctx.get("cache")) {
|
|
522
|
+
let res2 = await this.ctx.cache.get("contests", cid);
|
|
523
|
+
if (res2) return res2;
|
|
524
|
+
res2 = new ContestAdmin(this.ctx, cid, pw, this.config);
|
|
525
|
+
await res2.read();
|
|
526
|
+
await this.ctx.cache.set("contests", cid, res2, 1e3 * 600);
|
|
527
|
+
return res2;
|
|
528
|
+
}
|
|
529
|
+
const res = new ContestAdmin(this.ctx, cid, pw, this.config);
|
|
530
|
+
await res.read();
|
|
531
|
+
return res;
|
|
532
|
+
}
|
|
533
|
+
};
|
|
534
|
+
((MahjongPub2) => {
|
|
535
|
+
MahjongPub2.inject = {
|
|
536
|
+
required: ["database"],
|
|
537
|
+
optional: ["assets", "cache", "mahjong", "mahjong.database"]
|
|
538
|
+
};
|
|
539
|
+
MahjongPub2.Config = import_koishi.Schema.object({
|
|
540
|
+
informNotbind: import_koishi.Schema.boolean().default(false),
|
|
541
|
+
endpoint: import_koishi.Schema.string().default("https://cdn.r-mj.com/"),
|
|
542
|
+
batchInterval: import_koishi.Schema.natural().default(300),
|
|
543
|
+
batchCount: import_koishi.Schema.natural().default(10)
|
|
544
|
+
});
|
|
545
|
+
})(MahjongPub || (MahjongPub = {}));
|
|
546
|
+
var src_default = MahjongPub;
|
|
547
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
548
|
+
0 && (module.exports = {
|
|
549
|
+
MahjongPub
|
|
550
|
+
});
|