koishi-plugin-oni-sync-bot 0.6.2 → 0.7.1
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/dist/index.js +1 -1
- package/dist/style.css +1 -1
- package/lib/index.d.ts +7 -29
- package/lib/index.js +891 -386
- package/lib/plugins/consoleLogProvider.d.ts +13 -0
- package/lib/plugins/databaseExtension.d.ts +17 -0
- package/lib/plugins/queryCommands.d.ts +20 -0
- package/lib/plugins/routeRedirect.d.ts +15 -0
- package/lib/plugins/syncCommands.d.ts +23 -0
- package/lib/plugins/updateCommands.d.ts +15 -0
- package/lib/services/wikiBotService.d.ts +51 -0
- package/lib/utils/tools.d.ts +21 -0
- package/package.json +8 -1
- package/lib/config/index.d.ts +0 -14
- package/lib/service/logspush.d.ts +0 -16
- package/lib/service/router.d.ts +0 -9
- package/lib/synclib/imgSync.d.ts +0 -29
- package/lib/synclib/pageSync.d.ts +0 -29
- package/lib/task/imgs.d.ts +0 -8
- package/lib/task/index.d.ts +0 -8
- package/lib/task/modules.d.ts +0 -49
- package/lib/task/pages.d.ts +0 -8
- package/lib/task/sync.d.ts +0 -8
- package/lib/utils/login.d.ts +0 -8
- package/lib/wiki/querywiki.d.ts +0 -19
- package/lib/wiki/wikicore.d.ts +0 -25
package/lib/index.js
CHANGED
|
@@ -32,15 +32,14 @@ var src_exports = {};
|
|
|
32
32
|
__export(src_exports, {
|
|
33
33
|
Config: () => Config,
|
|
34
34
|
apply: () => apply,
|
|
35
|
-
inject: () => inject,
|
|
36
35
|
name: () => name
|
|
37
36
|
});
|
|
38
37
|
module.exports = __toCommonJS(src_exports);
|
|
39
|
-
var
|
|
38
|
+
var import_koishi11 = require("koishi");
|
|
40
39
|
var import_path = require("path");
|
|
41
|
-
var import_plugin_console = require("@koishijs/plugin-console");
|
|
42
40
|
|
|
43
|
-
// src/
|
|
41
|
+
// src/services/wikiBotService.ts
|
|
42
|
+
var import_koishi2 = require("koishi");
|
|
44
43
|
var import_mwn = require("mwn");
|
|
45
44
|
|
|
46
45
|
// src/utils/tools.ts
|
|
@@ -88,63 +87,383 @@ function generatePinyinInfo(text) {
|
|
|
88
87
|
};
|
|
89
88
|
}
|
|
90
89
|
__name(generatePinyinInfo, "generatePinyinInfo");
|
|
90
|
+
function getErrorMessage(error) {
|
|
91
|
+
if (error instanceof Error) {
|
|
92
|
+
return error.message;
|
|
93
|
+
}
|
|
94
|
+
return String(error);
|
|
95
|
+
}
|
|
96
|
+
__name(getErrorMessage, "getErrorMessage");
|
|
91
97
|
var logger = new import_koishi.Logger("oni-sync");
|
|
92
98
|
|
|
93
|
-
// src/
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
99
|
+
// src/services/wikiBotService.ts
|
|
100
|
+
var WikiBotService = class _WikiBotService extends import_koishi2.Service {
|
|
101
|
+
static {
|
|
102
|
+
__name(this, "WikiBotService");
|
|
103
|
+
}
|
|
104
|
+
static inject = [];
|
|
105
|
+
ggbot = null;
|
|
106
|
+
bwikibot = null;
|
|
107
|
+
isReady = false;
|
|
108
|
+
botConfig;
|
|
109
|
+
static USER_AGENT = `OniSyncBot/1.0 (https://klei.vip; Charles@klei.vip)`;
|
|
110
|
+
static MAX_RETRIES = 3;
|
|
111
|
+
static RETRY_DELAY = 5e3;
|
|
112
|
+
constructor(ctx, config) {
|
|
113
|
+
super(ctx, "wikiBot", true);
|
|
114
|
+
this.botConfig = config;
|
|
115
|
+
}
|
|
116
|
+
getSitesConfig() {
|
|
117
|
+
return {
|
|
118
|
+
gg: {
|
|
119
|
+
name: "WIKIGG",
|
|
120
|
+
api: "https://oxygennotincluded.wiki.gg/zh/api.php",
|
|
121
|
+
username: this.botConfig.ggUsername,
|
|
122
|
+
password: this.botConfig.ggPassword,
|
|
123
|
+
userAgent: _WikiBotService.USER_AGENT
|
|
124
|
+
},
|
|
125
|
+
bwiki: {
|
|
126
|
+
name: "bwiki",
|
|
127
|
+
api: "https://wiki.biligame.com/oni/api.php",
|
|
128
|
+
username: this.botConfig.bwikiusername,
|
|
129
|
+
password: this.botConfig.bwikipassword,
|
|
130
|
+
userAgent: _WikiBotService.USER_AGENT
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
delay(ms) {
|
|
135
|
+
return new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
136
|
+
}
|
|
137
|
+
async loginWithRetry(siteConfig, attempt = 1) {
|
|
138
|
+
try {
|
|
139
|
+
logger.info(
|
|
140
|
+
`正在登录 ${siteConfig.name}... (尝试 ${attempt}/${_WikiBotService.MAX_RETRIES})`
|
|
141
|
+
);
|
|
142
|
+
const bot = await this.login(siteConfig);
|
|
143
|
+
return bot;
|
|
144
|
+
} catch (error) {
|
|
145
|
+
const errorMsg = getErrorMessage(error);
|
|
146
|
+
if (attempt < _WikiBotService.MAX_RETRIES) {
|
|
147
|
+
logger.warn(
|
|
148
|
+
`登录 ${siteConfig.name} 失败,${_WikiBotService.RETRY_DELAY / 1e3}秒后重试...`,
|
|
149
|
+
errorMsg
|
|
150
|
+
);
|
|
151
|
+
await this.delay(_WikiBotService.RETRY_DELAY);
|
|
152
|
+
return this.loginWithRetry(siteConfig, attempt + 1);
|
|
153
|
+
}
|
|
154
|
+
logger.error(
|
|
155
|
+
`登录 ${siteConfig.name} 失败,已达到最大重试次数`,
|
|
156
|
+
errorMsg
|
|
157
|
+
);
|
|
158
|
+
throw error;
|
|
102
159
|
}
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
160
|
+
}
|
|
161
|
+
async login(siteConfig) {
|
|
162
|
+
logger.info(`正在连接 ${siteConfig.name} API: ${siteConfig.api}`);
|
|
163
|
+
const bot = new import_mwn.Mwn({
|
|
164
|
+
apiUrl: siteConfig.api,
|
|
165
|
+
username: siteConfig.username,
|
|
166
|
+
password: siteConfig.password,
|
|
167
|
+
userAgent: siteConfig.userAgent,
|
|
168
|
+
defaultParams: {
|
|
169
|
+
assert: "user"
|
|
170
|
+
},
|
|
171
|
+
maxRetries: 0,
|
|
172
|
+
retryPause: 0
|
|
108
173
|
});
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
174
|
+
if (siteConfig.name === "bwiki") {
|
|
175
|
+
const cookieString = "SESSDATA=666; Domain=wiki.biligame.com; Path=/oni; HttpOnly; Secure;";
|
|
176
|
+
bot.cookieJar.setCookie(cookieString, bot.options.apiUrl, (err) => {
|
|
177
|
+
if (err) {
|
|
178
|
+
logger.warn("Cookie 注入失败:", err);
|
|
179
|
+
} else {
|
|
180
|
+
logger.info("Cookie 注入成功");
|
|
181
|
+
}
|
|
182
|
+
});
|
|
183
|
+
bot.setRequestOptions({
|
|
184
|
+
headers: {
|
|
185
|
+
referer: "https://wiki.biligame.com/oni/",
|
|
186
|
+
"User-Agent": siteConfig.userAgent
|
|
187
|
+
}
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
logger.info(`正在执行 ${siteConfig.name} 登录...`);
|
|
191
|
+
await bot.login();
|
|
192
|
+
logger.info(`✅ 成功登录 ${siteConfig.name}`);
|
|
193
|
+
return bot;
|
|
194
|
+
}
|
|
195
|
+
async start() {
|
|
196
|
+
logger.info("WikiBotService 正在初始化...");
|
|
197
|
+
try {
|
|
198
|
+
const sitesConfig = this.getSitesConfig();
|
|
199
|
+
logger.info("开始登录 WIKIGG...");
|
|
200
|
+
try {
|
|
201
|
+
this.ggbot = await this.loginWithRetry(sitesConfig.gg);
|
|
202
|
+
} catch (error) {
|
|
203
|
+
const errorMsg = getErrorMessage(error);
|
|
204
|
+
logger.error(
|
|
205
|
+
"WIKIGG 登录失败,服务将继续运行,但 WIKIGG 相关功能不可用",
|
|
206
|
+
errorMsg
|
|
207
|
+
);
|
|
208
|
+
}
|
|
209
|
+
logger.info("开始登录 bwiki...");
|
|
210
|
+
try {
|
|
211
|
+
this.bwikibot = await this.loginWithRetry(sitesConfig.bwiki);
|
|
212
|
+
} catch (error) {
|
|
213
|
+
const errorMsg = getErrorMessage(error);
|
|
214
|
+
logger.error(
|
|
215
|
+
"bwiki 登录失败,服务将继续运行,但 bwiki 相关功能不可用",
|
|
216
|
+
errorMsg
|
|
217
|
+
);
|
|
218
|
+
}
|
|
219
|
+
if (this.ggbot && this.bwikibot) {
|
|
220
|
+
this.isReady = true;
|
|
221
|
+
logger.info("WikiBotService 初始化成功,两个 Wiki 已登录");
|
|
222
|
+
} else if (this.ggbot || this.bwikibot) {
|
|
223
|
+
this.isReady = true;
|
|
224
|
+
logger.warn(
|
|
225
|
+
`WikiBotService 部分初始化成功,已登录: ${this.ggbot ? "WIKIGG" : ""} ${this.bwikibot ? "bwiki" : ""}`
|
|
226
|
+
);
|
|
227
|
+
} else {
|
|
228
|
+
logger.error("WikiBotService 初始化失败,所有登录都失败");
|
|
229
|
+
}
|
|
230
|
+
} catch (error) {
|
|
231
|
+
const errorMsg = getErrorMessage(error);
|
|
232
|
+
logger.error("WikiBotService 初始化出错:", errorMsg);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
stop() {
|
|
236
|
+
this.isReady = false;
|
|
237
|
+
this.ggbot = null;
|
|
238
|
+
this.bwikibot = null;
|
|
239
|
+
logger.info("WikiBotService 已停止");
|
|
240
|
+
}
|
|
241
|
+
async relogin() {
|
|
242
|
+
const sitesConfig = this.getSitesConfig();
|
|
243
|
+
let ggSuccess = false;
|
|
244
|
+
let bwikiSuccess = false;
|
|
245
|
+
logger.info("开始重新登录 WIKIGG...");
|
|
246
|
+
try {
|
|
247
|
+
this.ggbot = await this.loginWithRetry(sitesConfig.gg);
|
|
248
|
+
ggSuccess = true;
|
|
249
|
+
logger.info("✅ 成功重新登录 WIKIGG");
|
|
250
|
+
} catch (error) {
|
|
251
|
+
this.ggbot = null;
|
|
252
|
+
const errorMsg = getErrorMessage(error);
|
|
253
|
+
logger.error("❌ 重新登录 WIKIGG 失败", errorMsg);
|
|
254
|
+
}
|
|
255
|
+
logger.info("开始重新登录 bwiki...");
|
|
256
|
+
try {
|
|
257
|
+
this.bwikibot = await this.loginWithRetry(sitesConfig.bwiki);
|
|
258
|
+
bwikiSuccess = true;
|
|
259
|
+
logger.info("✅ 成功重新登录 bwiki");
|
|
260
|
+
} catch (error) {
|
|
261
|
+
this.bwikibot = null;
|
|
262
|
+
const errorMsg = getErrorMessage(error);
|
|
263
|
+
logger.error("❌ 重新登录 bwiki 失败", errorMsg);
|
|
264
|
+
}
|
|
265
|
+
if (this.ggbot && this.bwikibot) {
|
|
266
|
+
this.isReady = true;
|
|
267
|
+
logger.info("WikiBotService 重新登录成功,两个 Wiki 已登录");
|
|
268
|
+
} else if (this.ggbot || this.bwikibot) {
|
|
269
|
+
this.isReady = true;
|
|
270
|
+
logger.warn(
|
|
271
|
+
`WikiBotService 部分重新登录成功,已登录: ${this.ggbot ? "WIKIGG" : ""} ${this.bwikibot ? "bwiki" : ""}`
|
|
272
|
+
);
|
|
273
|
+
} else {
|
|
274
|
+
this.isReady = false;
|
|
275
|
+
logger.error("WikiBotService 重新登录失败,所有登录都失败");
|
|
276
|
+
}
|
|
277
|
+
return { gg: ggSuccess, bwiki: bwikiSuccess };
|
|
278
|
+
}
|
|
279
|
+
async reloginSite(site) {
|
|
280
|
+
const sitesConfig = this.getSitesConfig();
|
|
281
|
+
const siteConfig = site === "gg" ? sitesConfig.gg : sitesConfig.bwiki;
|
|
282
|
+
try {
|
|
283
|
+
const bot = await this.loginWithRetry(siteConfig);
|
|
284
|
+
if (site === "gg") {
|
|
285
|
+
this.ggbot = bot;
|
|
286
|
+
} else {
|
|
287
|
+
this.bwikibot = bot;
|
|
288
|
+
}
|
|
289
|
+
logger.info(`✅ ${siteConfig.name} 自动重新登录成功`);
|
|
290
|
+
} catch (error) {
|
|
291
|
+
const errorMsg = getErrorMessage(error);
|
|
292
|
+
if (site === "gg") {
|
|
293
|
+
this.ggbot = null;
|
|
294
|
+
} else {
|
|
295
|
+
this.bwikibot = null;
|
|
296
|
+
}
|
|
297
|
+
logger.error(`❌ ${siteConfig.name} 自动重新登录失败`, errorMsg);
|
|
298
|
+
throw error;
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
isGGBotReady() {
|
|
302
|
+
return this.ggbot !== null;
|
|
303
|
+
}
|
|
304
|
+
isBWikiBotReady() {
|
|
305
|
+
return this.bwikibot !== null;
|
|
306
|
+
}
|
|
307
|
+
createBotProxy(bot, site) {
|
|
308
|
+
const self = this;
|
|
309
|
+
return new Proxy(bot, {
|
|
310
|
+
get(target, prop) {
|
|
311
|
+
const originalMethod = target[prop];
|
|
312
|
+
if (typeof originalMethod !== "function") {
|
|
313
|
+
return originalMethod;
|
|
314
|
+
}
|
|
315
|
+
return async function(...args) {
|
|
316
|
+
try {
|
|
317
|
+
return await originalMethod.apply(target, args);
|
|
318
|
+
} catch (error) {
|
|
319
|
+
if (error.code === "assertuserfailed") {
|
|
320
|
+
logger.warn(
|
|
321
|
+
`检测到 ${site === "gg" ? "WIKIGG" : "bwiki"} 登录过期,正在自动重新登录...`
|
|
322
|
+
);
|
|
323
|
+
await self.reloginSite(site);
|
|
324
|
+
const newBot = site === "gg" ? self.ggbot : self.bwikibot;
|
|
325
|
+
if (!newBot) {
|
|
326
|
+
throw new Error(
|
|
327
|
+
`${site === "gg" ? "WIKIGG" : "bwiki"} 自动重新登录失败`
|
|
328
|
+
);
|
|
329
|
+
}
|
|
330
|
+
return await newBot[prop].apply(newBot, args);
|
|
331
|
+
}
|
|
332
|
+
throw error;
|
|
333
|
+
}
|
|
334
|
+
};
|
|
112
335
|
}
|
|
113
336
|
});
|
|
114
337
|
}
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
}
|
|
119
|
-
__name(login, "login");
|
|
120
|
-
|
|
121
|
-
// src/config/index.ts
|
|
122
|
-
var userAgent = `OniSyncBot/1.0 (https://klei.vip; Charles@klei.vip)`;
|
|
123
|
-
function getSitesConfig(config) {
|
|
124
|
-
return {
|
|
125
|
-
gg: {
|
|
126
|
-
name: "WIKIGG",
|
|
127
|
-
api: "https://oxygennotincluded.wiki.gg/zh/api.php",
|
|
128
|
-
username: config.ggUsername,
|
|
129
|
-
password: config.ggPassword,
|
|
130
|
-
userAgent
|
|
131
|
-
},
|
|
132
|
-
bwiki: {
|
|
133
|
-
name: "bwiki",
|
|
134
|
-
api: "https://wiki.biligame.com/oni/api.php",
|
|
135
|
-
username: config.bwikiusername,
|
|
136
|
-
password: config.bwikipassword,
|
|
137
|
-
userAgent
|
|
338
|
+
getGGBot() {
|
|
339
|
+
if (!this.ggbot) {
|
|
340
|
+
throw new Error("WIKIGG bot 尚未就绪,请检查登录配置或查看日志");
|
|
138
341
|
}
|
|
139
|
-
|
|
140
|
-
}
|
|
141
|
-
|
|
342
|
+
return this.createBotProxy(this.ggbot, "gg");
|
|
343
|
+
}
|
|
344
|
+
getBWikiBot() {
|
|
345
|
+
if (!this.bwikibot) {
|
|
346
|
+
throw new Error("bwiki bot 尚未就绪,请检查登录配置或查看日志");
|
|
347
|
+
}
|
|
348
|
+
return this.createBotProxy(this.bwikibot, "bwiki");
|
|
349
|
+
}
|
|
350
|
+
};
|
|
351
|
+
((WikiBotService2) => {
|
|
352
|
+
WikiBotService2.Config = import_koishi2.Schema.object({
|
|
353
|
+
ggUsername: import_koishi2.Schema.string().description("WIKIGG 用户名").default("1"),
|
|
354
|
+
ggPassword: import_koishi2.Schema.string().description("WIKIGG 密码").default("1"),
|
|
355
|
+
bwikiusername: import_koishi2.Schema.string().description("bwiki用户名").default("1"),
|
|
356
|
+
bwikipassword: import_koishi2.Schema.string().description("bwiki密码").default("1")
|
|
357
|
+
});
|
|
358
|
+
})(WikiBotService || (WikiBotService = {}));
|
|
142
359
|
|
|
143
|
-
// src/
|
|
360
|
+
// src/plugins/consoleLogProvider.ts
|
|
144
361
|
var import_koishi3 = require("koishi");
|
|
362
|
+
var import_plugin_console = require("@koishijs/plugin-console");
|
|
363
|
+
var logBuffer = [];
|
|
364
|
+
var PublicLogProvider = class extends import_plugin_console.DataService {
|
|
365
|
+
static {
|
|
366
|
+
__name(this, "PublicLogProvider");
|
|
367
|
+
}
|
|
368
|
+
constructor(ctx) {
|
|
369
|
+
super(ctx, "onilogs", { authority: 0 });
|
|
370
|
+
}
|
|
371
|
+
async get() {
|
|
372
|
+
return logBuffer;
|
|
373
|
+
}
|
|
374
|
+
};
|
|
375
|
+
var ConsoleLogProvider = class {
|
|
376
|
+
static {
|
|
377
|
+
__name(this, "ConsoleLogProvider");
|
|
378
|
+
}
|
|
379
|
+
static inject = ["console"];
|
|
380
|
+
constructor(ctx) {
|
|
381
|
+
ctx.plugin(PublicLogProvider);
|
|
382
|
+
const target = {
|
|
383
|
+
colors: 0,
|
|
384
|
+
record: /* @__PURE__ */ __name((record) => {
|
|
385
|
+
if (record.name !== "oni-sync") return;
|
|
386
|
+
logBuffer.push(record);
|
|
387
|
+
if (logBuffer.length > 1e3) {
|
|
388
|
+
logBuffer = logBuffer.slice(-1e3);
|
|
389
|
+
}
|
|
390
|
+
ctx.get("console")?.patch("onilogs", logBuffer);
|
|
391
|
+
}, "record")
|
|
392
|
+
};
|
|
393
|
+
import_koishi3.Logger.targets.push(target);
|
|
394
|
+
ctx.on("dispose", () => {
|
|
395
|
+
const index = import_koishi3.Logger.targets.indexOf(target);
|
|
396
|
+
if (index > -1) import_koishi3.Logger.targets.splice(index, 1);
|
|
397
|
+
});
|
|
398
|
+
}
|
|
399
|
+
};
|
|
400
|
+
|
|
401
|
+
// src/plugins/databaseExtension.ts
|
|
402
|
+
var DatabaseExtension = class {
|
|
403
|
+
static {
|
|
404
|
+
__name(this, "DatabaseExtension");
|
|
405
|
+
}
|
|
406
|
+
static inject = ["database"];
|
|
407
|
+
constructor(ctx) {
|
|
408
|
+
ctx.model.extend("wikipages", {
|
|
409
|
+
id: "integer",
|
|
410
|
+
title: "string",
|
|
411
|
+
pinyin_full: "string",
|
|
412
|
+
pinyin_first: "string"
|
|
413
|
+
});
|
|
414
|
+
}
|
|
415
|
+
};
|
|
416
|
+
|
|
417
|
+
// src/plugins/routeRedirect.ts
|
|
418
|
+
var import_koishi4 = require("koishi");
|
|
419
|
+
var RouteRedirect = class {
|
|
420
|
+
static {
|
|
421
|
+
__name(this, "RouteRedirect");
|
|
422
|
+
}
|
|
423
|
+
static inject = ["database", "server"];
|
|
424
|
+
config;
|
|
425
|
+
constructor(ctx, config) {
|
|
426
|
+
this.config = config;
|
|
427
|
+
ctx.server.get("/gg/:id", async (router) => {
|
|
428
|
+
const pageId = Number(router.params.id);
|
|
429
|
+
if (isNaN(pageId)) return router.body = "❌ 无效的页面ID,必须为数字!";
|
|
430
|
+
const [page] = await ctx.database.get("wikipages", { id: pageId });
|
|
431
|
+
if (!page)
|
|
432
|
+
return router.body = `❌ 未找到ID为【${pageId}】的页面,请联系管理员更新缓存!`;
|
|
433
|
+
const targetUrl = `https://${this.config.main_site}/${encodeURIComponent(
|
|
434
|
+
page.title
|
|
435
|
+
)}?variant=zh`;
|
|
436
|
+
router.redirect(targetUrl);
|
|
437
|
+
});
|
|
438
|
+
ctx.server.get("/bw/:id", async (router) => {
|
|
439
|
+
const pageId = Number(router.params.id);
|
|
440
|
+
if (isNaN(pageId)) return router.body = "❌ 无效的页面ID,必须为数字!";
|
|
441
|
+
const [page] = await ctx.database.get("wikipages", { id: pageId });
|
|
442
|
+
if (!page)
|
|
443
|
+
return router.body = `❌ 未找到ID为【${pageId}】的页面,请联系管理员更新缓存!`;
|
|
444
|
+
const targetUrl = `https://${this.config.bwiki_site}/${encodeURIComponent(
|
|
445
|
+
page.title
|
|
446
|
+
)}`;
|
|
447
|
+
router.redirect(targetUrl);
|
|
448
|
+
});
|
|
449
|
+
}
|
|
450
|
+
};
|
|
451
|
+
((RouteRedirect2) => {
|
|
452
|
+
RouteRedirect2.Config = import_koishi4.Schema.object({
|
|
453
|
+
domain: import_koishi4.Schema.string().description("你的短链域名(必填,如:klei.vip)").default("klei.vip"),
|
|
454
|
+
main_site: import_koishi4.Schema.string().description("主站域名(必填,如:oxygennotincluded.wiki.gg)").default("oxygennotincluded.wiki.gg/zh"),
|
|
455
|
+
bwiki_site: import_koishi4.Schema.string().description("镜像站域名(必填,如:wiki.biligame.com)").default("wiki.biligame.com/oni")
|
|
456
|
+
});
|
|
457
|
+
})(RouteRedirect || (RouteRedirect = {}));
|
|
458
|
+
|
|
459
|
+
// src/plugins/syncCommands.ts
|
|
460
|
+
var import_koishi8 = require("koishi");
|
|
461
|
+
|
|
462
|
+
// src/sync/pageSync.ts
|
|
463
|
+
var import_koishi6 = require("koishi");
|
|
145
464
|
|
|
146
465
|
// src/sync/imgSync.ts
|
|
147
|
-
var
|
|
466
|
+
var import_koishi5 = require("koishi");
|
|
148
467
|
var import_node_fetch = __toESM(require("node-fetch"));
|
|
149
468
|
var import_form_data = __toESM(require("form-data"));
|
|
150
469
|
var CONFIG = {
|
|
@@ -174,11 +493,56 @@ async function getImageInfo(site, fileName) {
|
|
|
174
493
|
size: imageInfo.size
|
|
175
494
|
};
|
|
176
495
|
} catch (error) {
|
|
177
|
-
|
|
496
|
+
const errorMsg = getErrorMessage(error);
|
|
497
|
+
logger.error(`[GetImageInfo] 获取 ${fileName} 信息失败:`, errorMsg);
|
|
178
498
|
return null;
|
|
179
499
|
}
|
|
180
500
|
}
|
|
181
501
|
__name(getImageInfo, "getImageInfo");
|
|
502
|
+
async function deleteOldVersions(bot, fileName) {
|
|
503
|
+
try {
|
|
504
|
+
const response = await bot.query({
|
|
505
|
+
action: "query",
|
|
506
|
+
titles: fileName,
|
|
507
|
+
prop: "revisions",
|
|
508
|
+
rvprop: "ids|timestamp",
|
|
509
|
+
rvlimit: "max",
|
|
510
|
+
rvdir: "newer"
|
|
511
|
+
// 按时间正序排列,最新的在最后
|
|
512
|
+
});
|
|
513
|
+
const pages = response.query?.pages || {};
|
|
514
|
+
const page = Object.values(pages)[0];
|
|
515
|
+
if (!page || !page.revisions || page.revisions.length <= 1) {
|
|
516
|
+
return;
|
|
517
|
+
}
|
|
518
|
+
const revisionIds = page.revisions.slice(0, -1).map((rev) => rev.revid);
|
|
519
|
+
const token = await bot.getCsrfToken();
|
|
520
|
+
for (const revid of revisionIds) {
|
|
521
|
+
try {
|
|
522
|
+
await bot.rawRequest({
|
|
523
|
+
method: "POST",
|
|
524
|
+
url: bot.options.apiUrl,
|
|
525
|
+
data: {
|
|
526
|
+
action: "delete",
|
|
527
|
+
title: fileName,
|
|
528
|
+
revid,
|
|
529
|
+
token,
|
|
530
|
+
reason: "自动清理旧版本,只保留最新同步版本",
|
|
531
|
+
format: "json"
|
|
532
|
+
}
|
|
533
|
+
});
|
|
534
|
+
logger.info(`[SyncImg] 🗑️ 删除旧版本 ${revid} 成功`);
|
|
535
|
+
} catch (error) {
|
|
536
|
+
const errorMsg = getErrorMessage(error);
|
|
537
|
+
logger.error(`[SyncImg] ❌ 删除旧版本 ${revid} 失败:`, errorMsg);
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
} catch (error) {
|
|
541
|
+
const errorMsg = getErrorMessage(error);
|
|
542
|
+
logger.error(`[SyncImg] ❌ 获取版本信息失败:`, errorMsg);
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
__name(deleteOldVersions, "deleteOldVersions");
|
|
182
546
|
async function syncSingleImage(sourceBot, targetBot, fileName, config) {
|
|
183
547
|
if (CONFIG.IGNORED_IMAGES.includes(fileName)) {
|
|
184
548
|
logger.info(`[SyncImg] 🚫 图片 ${fileName} 在忽略列表,跳过`);
|
|
@@ -193,7 +557,7 @@ async function syncSingleImage(sourceBot, targetBot, fileName, config) {
|
|
|
193
557
|
}
|
|
194
558
|
const targetImageInfo = await getImageInfo(targetBot, fileName);
|
|
195
559
|
logger.info(`原图片sha1: ${sourceImageInfo.sha1}`);
|
|
196
|
-
logger.info(`目标图片sha1: ${targetImageInfo
|
|
560
|
+
logger.info(`目标图片sha1: ${targetImageInfo?.sha1}`);
|
|
197
561
|
if (targetImageInfo && targetImageInfo.sha1 === sourceImageInfo.sha1) {
|
|
198
562
|
logger.info(`[SyncImg] 🟡 图片 ${fileName} 已存在且内容一致,跳过`);
|
|
199
563
|
return { success: true, reason: "no_change" };
|
|
@@ -236,6 +600,7 @@ async function syncSingleImage(sourceBot, targetBot, fileName, config) {
|
|
|
236
600
|
const responseData = rawResponse.data;
|
|
237
601
|
if (responseData.upload && responseData.upload.result === "Success") {
|
|
238
602
|
logger.info(`[SyncImg] ✅ 图片 ${fileName} 同步成功`);
|
|
603
|
+
await deleteOldVersions(targetBot, fileName);
|
|
239
604
|
return { success: true, reason: "synced" };
|
|
240
605
|
} else if (responseData.error) {
|
|
241
606
|
throw new Error(`${responseData.error.code}: ${responseData.error.info}`);
|
|
@@ -303,13 +668,13 @@ async function syncAllImages(sourceBot, targetBot, config) {
|
|
|
303
668
|
if (!result.success) {
|
|
304
669
|
failCount++;
|
|
305
670
|
failedImages.push(fileName);
|
|
306
|
-
await (0,
|
|
671
|
+
await (0, import_koishi5.sleep)(CONFIG.SYNC_INTERVAL_FAILED);
|
|
307
672
|
} else {
|
|
308
673
|
successCount++;
|
|
309
674
|
if (result.reason === "ignored" || result.reason === "no_change") {
|
|
310
675
|
skipCount++;
|
|
311
676
|
}
|
|
312
|
-
await (0,
|
|
677
|
+
await (0, import_koishi5.sleep)(CONFIG.SYNC_INTERVAL_SUCCESS);
|
|
313
678
|
}
|
|
314
679
|
}
|
|
315
680
|
if (failedImages.length > 0) {
|
|
@@ -335,7 +700,7 @@ async function syncAllImages(sourceBot, targetBot, config) {
|
|
|
335
700
|
stillFailed.push(fileName);
|
|
336
701
|
logger.info(`[SyncAllImg] ❌ 重试失败: ${fileName}`);
|
|
337
702
|
}
|
|
338
|
-
await (0,
|
|
703
|
+
await (0, import_koishi5.sleep)(CONFIG.SYNC_INTERVAL_SUCCESS);
|
|
339
704
|
}
|
|
340
705
|
if (stillFailed.length > 0) {
|
|
341
706
|
logger.info(`
|
|
@@ -422,13 +787,13 @@ async function processPageWithStats(oldSite, newSite, pageTitle, user, stats, fa
|
|
|
422
787
|
if (!syncResult.success) {
|
|
423
788
|
stats.failCount++;
|
|
424
789
|
failedPages.push(pageTitle);
|
|
425
|
-
await (0,
|
|
790
|
+
await (0, import_koishi6.sleep)(CONFIG2.SYNC_INTERVAL_FAILED);
|
|
426
791
|
} else {
|
|
427
792
|
stats.successCount++;
|
|
428
793
|
if (syncResult.reason === "ignored" || syncResult.reason === "no_change") {
|
|
429
794
|
stats.skipCount++;
|
|
430
795
|
}
|
|
431
|
-
await (0,
|
|
796
|
+
await (0, import_koishi6.sleep)(CONFIG2.SYNC_INTERVAL_SUCCESS);
|
|
432
797
|
}
|
|
433
798
|
}
|
|
434
799
|
__name(processPageWithStats, "processPageWithStats");
|
|
@@ -504,11 +869,11 @@ async function syncPages(oldSite, newSite) {
|
|
|
504
869
|
stats.skipCount++;
|
|
505
870
|
}
|
|
506
871
|
logger.info(`[SyncAllPages] ✅ 页面 ${pageTitle} 重试成功`);
|
|
507
|
-
await (0,
|
|
872
|
+
await (0, import_koishi6.sleep)(CONFIG2.SYNC_INTERVAL_SUCCESS);
|
|
508
873
|
} else {
|
|
509
874
|
stillFailed.push(pageTitle);
|
|
510
875
|
logger.info(`[SyncAllPages] ❌ 页面 ${pageTitle} 再次失败`);
|
|
511
|
-
await (0,
|
|
876
|
+
await (0, import_koishi6.sleep)(CONFIG2.SYNC_INTERVAL_FAILED);
|
|
512
877
|
}
|
|
513
878
|
}
|
|
514
879
|
}
|
|
@@ -577,11 +942,11 @@ async function incrementalUpdate(oldSite, newSite, config) {
|
|
|
577
942
|
CONFIG2.INCREMENTAL_USER
|
|
578
943
|
);
|
|
579
944
|
}
|
|
580
|
-
await (0,
|
|
945
|
+
await (0, import_koishi6.sleep)(CONFIG2.SYNC_INTERVAL_SUCCESS);
|
|
581
946
|
} catch (error) {
|
|
582
947
|
const errMsg = error instanceof Error ? error.message : String(error);
|
|
583
948
|
logger.error(`[增量更新流程] ❌ 处理 ${title} 时出错:`, errMsg);
|
|
584
|
-
await (0,
|
|
949
|
+
await (0, import_koishi6.sleep)(CONFIG2.SYNC_INTERVAL_FAILED);
|
|
585
950
|
}
|
|
586
951
|
}
|
|
587
952
|
}
|
|
@@ -596,7 +961,7 @@ async function incrementalUpdate(oldSite, newSite, config) {
|
|
|
596
961
|
__name(incrementalUpdate, "incrementalUpdate");
|
|
597
962
|
|
|
598
963
|
// src/sync/moduleSync.ts
|
|
599
|
-
var
|
|
964
|
+
var import_koishi7 = require("koishi");
|
|
600
965
|
var CONFIG3 = {
|
|
601
966
|
MODLE_NAMESPACE: 828,
|
|
602
967
|
// 模块命名空间 (注意:这里原代码拼写为 MODLE,保留原样)
|
|
@@ -700,13 +1065,13 @@ async function syncModules(oldSite, newSite) {
|
|
|
700
1065
|
if (!syncResult.success) {
|
|
701
1066
|
failCount++;
|
|
702
1067
|
failedModules.push(moduleTitle);
|
|
703
|
-
await (0,
|
|
1068
|
+
await (0, import_koishi7.sleep)(CONFIG3.SYNC_INTERVAL_FAILED);
|
|
704
1069
|
} else {
|
|
705
1070
|
successCount++;
|
|
706
1071
|
if (syncResult.reason === "ignored" || syncResult.reason === "no_change") {
|
|
707
1072
|
skipCount++;
|
|
708
1073
|
}
|
|
709
|
-
await (0,
|
|
1074
|
+
await (0, import_koishi7.sleep)(CONFIG3.SYNC_INTERVAL_SUCCESS);
|
|
710
1075
|
}
|
|
711
1076
|
}
|
|
712
1077
|
if (failedModules.length > 0) {
|
|
@@ -731,11 +1096,11 @@ async function syncModules(oldSite, newSite) {
|
|
|
731
1096
|
skipCount++;
|
|
732
1097
|
}
|
|
733
1098
|
logger.info(`[SyncAllModules] ✅ 模块 ${moduleTitle} 重试成功`);
|
|
734
|
-
await (0,
|
|
1099
|
+
await (0, import_koishi7.sleep)(CONFIG3.SYNC_INTERVAL_SUCCESS);
|
|
735
1100
|
} else {
|
|
736
1101
|
stillFailed.push(moduleTitle);
|
|
737
1102
|
logger.info(`[SyncAllModules] ❌ 模块 ${moduleTitle} 再次失败`);
|
|
738
|
-
await (0,
|
|
1103
|
+
await (0, import_koishi7.sleep)(CONFIG3.SYNC_INTERVAL_FAILED);
|
|
739
1104
|
}
|
|
740
1105
|
}
|
|
741
1106
|
logger.info(`
|
|
@@ -755,303 +1120,366 @@ async function syncModules(oldSite, newSite) {
|
|
|
755
1120
|
logger.info(`├─ 成功:${successCount} 个(含跳过 ${skipCount} 个)`);
|
|
756
1121
|
logger.info(`└─ 失败:${failCount} 个`);
|
|
757
1122
|
} catch (error) {
|
|
758
|
-
|
|
1123
|
+
const errorMsg = getErrorMessage(error);
|
|
1124
|
+
logger.error(`[SyncAllModules] 💥 批量同步流程异常终止:`, errorMsg);
|
|
759
1125
|
throw error;
|
|
760
1126
|
}
|
|
761
1127
|
}
|
|
762
1128
|
__name(syncModules, "syncModules");
|
|
763
1129
|
|
|
764
|
-
// src/
|
|
765
|
-
var
|
|
766
|
-
var inject = ["console", "database", "server", "cron"];
|
|
767
|
-
var logBuffer = [];
|
|
768
|
-
var Config = import_koishi5.Schema.object({
|
|
769
|
-
ggUsername: import_koishi5.Schema.string().description("WIKIGG 用户名").default("1"),
|
|
770
|
-
ggPassword: import_koishi5.Schema.string().description("WIKIGG 密码").default("1"),
|
|
771
|
-
bwikiusername: import_koishi5.Schema.string().description("bwiki用户名").default("1"),
|
|
772
|
-
bwikipassword: import_koishi5.Schema.string().description("bwiki密码").default("1"),
|
|
773
|
-
domain: import_koishi5.Schema.string().description("你的短链域名(必填,如:klei.vip)").default("klei.vip"),
|
|
774
|
-
main_site: import_koishi5.Schema.string().description("主站域名(必填,如:oxygennotincluded.wiki.gg)").default("oxygennotincluded.wiki.gg/zh"),
|
|
775
|
-
bwiki_site: import_koishi5.Schema.string().description("镜像站域名(必填,如:wiki.biligame.com)").default("wiki.biligame.com/oni"),
|
|
776
|
-
logsUrl: import_koishi5.Schema.string().description("日志查看地址").default("https://klei.vip/onilogs")
|
|
777
|
-
});
|
|
778
|
-
var PublicLogProvider = class extends import_plugin_console.DataService {
|
|
1130
|
+
// src/plugins/syncCommands.ts
|
|
1131
|
+
var SyncCommands = class {
|
|
779
1132
|
static {
|
|
780
|
-
__name(this, "
|
|
781
|
-
}
|
|
782
|
-
constructor(ctx) {
|
|
783
|
-
super(ctx, "onilogs", { authority: 0 });
|
|
784
|
-
}
|
|
785
|
-
async get() {
|
|
786
|
-
return logBuffer;
|
|
1133
|
+
__name(this, "SyncCommands");
|
|
787
1134
|
}
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
dev: (0, import_path.resolve)(__dirname, "../client/index.ts"),
|
|
796
|
-
prod: (0, import_path.resolve)(__dirname, "../dist")
|
|
797
|
-
});
|
|
798
|
-
});
|
|
799
|
-
ctx.plugin(PublicLogProvider);
|
|
800
|
-
const target = {
|
|
801
|
-
colors: 0,
|
|
802
|
-
record: /* @__PURE__ */ __name((record) => {
|
|
803
|
-
if (record.name !== "oni-sync") return;
|
|
804
|
-
logBuffer.push(record);
|
|
805
|
-
if (logBuffer.length > 100) {
|
|
806
|
-
logBuffer = logBuffer.slice(-100);
|
|
807
|
-
}
|
|
808
|
-
ctx.get("console")?.patch("onilogs", logBuffer);
|
|
809
|
-
}, "record")
|
|
810
|
-
};
|
|
811
|
-
import_koishi5.Logger.targets.push(target);
|
|
812
|
-
ctx.on("dispose", () => {
|
|
813
|
-
const index = import_koishi5.Logger.targets.indexOf(target);
|
|
814
|
-
if (index > -1) import_koishi5.Logger.targets.splice(index, 1);
|
|
815
|
-
});
|
|
816
|
-
ctx.model.extend("wikipages", {
|
|
817
|
-
id: "integer",
|
|
818
|
-
title: "string",
|
|
819
|
-
pinyin_full: "string",
|
|
820
|
-
// 全拼
|
|
821
|
-
pinyin_first: "string"
|
|
822
|
-
// 首字母
|
|
823
|
-
});
|
|
824
|
-
ctx.server.get("/gg/:id", async (router) => {
|
|
825
|
-
const pageId = Number(router.params.id);
|
|
826
|
-
if (isNaN(pageId)) return router.body = "❌ 无效的页面ID,必须为数字!";
|
|
827
|
-
const [page] = await ctx.database.get("wikipages", { id: pageId });
|
|
828
|
-
if (!page)
|
|
829
|
-
return router.body = `❌ 未找到ID为【${pageId}】的页面,请联系管理员更新缓存!`;
|
|
830
|
-
const targetUrl = `https://${config.main_site}/${encodeURIComponent(
|
|
831
|
-
page.title
|
|
832
|
-
)}?variant=zh`;
|
|
833
|
-
router.redirect(targetUrl);
|
|
834
|
-
});
|
|
835
|
-
ctx.server.get("/bw/:id", async (router) => {
|
|
836
|
-
const pageId = Number(router.params.id);
|
|
837
|
-
if (isNaN(pageId)) return router.body = "❌ 无效的页面ID,必须为数字!";
|
|
838
|
-
const [page] = await ctx.database.get("wikipages", { id: pageId });
|
|
839
|
-
if (!page)
|
|
840
|
-
return router.body = `❌ 未找到ID为【${pageId}】的页面,请联系管理员更新缓存!`;
|
|
841
|
-
const targetUrl = `https://${config.bwiki_site}/${encodeURIComponent(
|
|
842
|
-
page.title
|
|
843
|
-
)}`;
|
|
844
|
-
router.redirect(targetUrl);
|
|
845
|
-
});
|
|
846
|
-
ctx.on("ready", async () => {
|
|
847
|
-
logger.info("初始化中...");
|
|
848
|
-
const sitesConfig = getSitesConfig(config);
|
|
849
|
-
ggbot = await login(sitesConfig.gg);
|
|
850
|
-
bwikibot = await login(sitesConfig.bwiki);
|
|
851
|
-
if (ggbot.login && bwikibot.login) {
|
|
852
|
-
logger.info("登录成功,插件已准备就绪");
|
|
853
|
-
} else {
|
|
854
|
-
logger.error("登录失败,请检查配置");
|
|
855
|
-
}
|
|
1135
|
+
static inject = ["wikiBot", "cron"];
|
|
1136
|
+
config;
|
|
1137
|
+
log;
|
|
1138
|
+
constructor(ctx, config) {
|
|
1139
|
+
this.config = config;
|
|
1140
|
+
this.log = ctx.logger("oni-sync");
|
|
1141
|
+
logger.info("WikiBot 服务已就绪,初始化定时任务和指令");
|
|
856
1142
|
ctx.cron("15 * * * *", async () => {
|
|
857
|
-
|
|
1143
|
+
if (!ctx.wikiBot.isGGBotReady() || !ctx.wikiBot.isBWikiBotReady()) {
|
|
1144
|
+
logger.warn("增量更新跳过:Wiki 机器人未就绪");
|
|
1145
|
+
return;
|
|
1146
|
+
}
|
|
1147
|
+
await incrementalUpdate(
|
|
1148
|
+
ctx.wikiBot.getGGBot(),
|
|
1149
|
+
ctx.wikiBot.getBWikiBot(),
|
|
1150
|
+
config
|
|
1151
|
+
);
|
|
858
1152
|
});
|
|
859
1153
|
ctx.cron("30 8 * * 4", async () => {
|
|
860
|
-
|
|
1154
|
+
if (!ctx.wikiBot.isGGBotReady() || !ctx.wikiBot.isBWikiBotReady()) {
|
|
1155
|
+
logger.warn("同步所有页面跳过:Wiki 机器人未就绪");
|
|
1156
|
+
return;
|
|
1157
|
+
}
|
|
1158
|
+
await syncPages(ctx.wikiBot.getGGBot(), ctx.wikiBot.getBWikiBot()).then(() => {
|
|
861
1159
|
logger.info("自动任务:尝试同步所有页面,从 WIKIGG 到 bwiki");
|
|
862
1160
|
}).catch((err) => {
|
|
863
1161
|
logger.error(`同步所有页面失败`);
|
|
864
|
-
log.error(`,错误信息:${err}`);
|
|
1162
|
+
this.log.error(`,错误信息:${err}`);
|
|
865
1163
|
});
|
|
866
1164
|
});
|
|
867
1165
|
ctx.cron("30 8 * * 3", async () => {
|
|
868
|
-
|
|
1166
|
+
if (!ctx.wikiBot.isGGBotReady() || !ctx.wikiBot.isBWikiBotReady()) {
|
|
1167
|
+
logger.warn("同步所有图片跳过:Wiki 机器人未就绪");
|
|
1168
|
+
return;
|
|
1169
|
+
}
|
|
1170
|
+
await syncAllImages(
|
|
1171
|
+
ctx.wikiBot.getGGBot(),
|
|
1172
|
+
ctx.wikiBot.getBWikiBot(),
|
|
1173
|
+
config
|
|
1174
|
+
).then(() => {
|
|
869
1175
|
logger.info("自动任务:尝试同步所有图片,从 WIKIGG 到 bwiki");
|
|
870
1176
|
}).catch((err) => {
|
|
871
1177
|
logger.error(`同步所有图片失败`);
|
|
872
|
-
log.error(`,错误信息:${err}`);
|
|
1178
|
+
this.log.error(`,错误信息:${err}`);
|
|
873
1179
|
});
|
|
874
1180
|
});
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
1181
|
+
this.registerCommands(ctx);
|
|
1182
|
+
}
|
|
1183
|
+
checkBotsReady(ctx) {
|
|
1184
|
+
const ggReady = ctx.wikiBot.isGGBotReady();
|
|
1185
|
+
const bwReady = ctx.wikiBot.isBWikiBotReady();
|
|
1186
|
+
return ggReady && bwReady;
|
|
1187
|
+
}
|
|
1188
|
+
registerCommands(ctx) {
|
|
1189
|
+
ctx.command("sync <pageTitle:string>", "同步指定页面", { authority: 2 }).action(async ({ session }, pageTitle) => {
|
|
1190
|
+
if (!this.checkBotsReady(ctx)) {
|
|
1191
|
+
return session.send("❌ Wiki 机器人未就绪,请检查登录配置或查看日志");
|
|
1192
|
+
}
|
|
1193
|
+
await syncSinglePage(
|
|
1194
|
+
ctx.wikiBot.getGGBot(),
|
|
1195
|
+
ctx.wikiBot.getBWikiBot(),
|
|
1196
|
+
pageTitle,
|
|
1197
|
+
"sync-bot"
|
|
1198
|
+
).then(() => {
|
|
1199
|
+
session.send(
|
|
1200
|
+
`✅ 已尝试同步页面:${pageTitle},请前往控制台查看:${this.config.logsUrl}`
|
|
1201
|
+
);
|
|
1202
|
+
}).catch((err) => {
|
|
1203
|
+
session.send(`❌ 同步页面失败:${pageTitle}`);
|
|
1204
|
+
this.log.error(`,错误信息:${err}`);
|
|
1205
|
+
});
|
|
884
1206
|
});
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
);
|
|
892
|
-
await incrementalUpdate(ggbot, bwikibot, config).then(() => {
|
|
893
|
-
session.send(
|
|
894
|
-
`✅ 已尝试获取三小时前的编辑并同步,请前往控制台查看:${config.logsUrl}`
|
|
895
|
-
);
|
|
896
|
-
}).catch((err) => {
|
|
1207
|
+
ctx.command("sync.incrementalUpdate", "获取3h内的编辑并尝试更新", {
|
|
1208
|
+
authority: 2
|
|
1209
|
+
}).alias("增量更新").action(async ({ session }) => {
|
|
1210
|
+
if (!this.checkBotsReady(ctx)) {
|
|
1211
|
+
return session.send("❌ Wiki 机器人未就绪,请检查登录配置或查看日志");
|
|
1212
|
+
}
|
|
897
1213
|
session.send(
|
|
898
|
-
|
|
1214
|
+
`🚀 获取3h内的编辑并尝试更新,任务耗时可能较长,请前往控制台查看日志:${this.config.logsUrl}`
|
|
899
1215
|
);
|
|
900
|
-
|
|
1216
|
+
await incrementalUpdate(
|
|
1217
|
+
ctx.wikiBot.getGGBot(),
|
|
1218
|
+
ctx.wikiBot.getBWikiBot(),
|
|
1219
|
+
this.config
|
|
1220
|
+
).then(() => {
|
|
1221
|
+
session.send(
|
|
1222
|
+
`✅ 已尝试获取三小时前的编辑并同步,请前往控制台查看:${this.config.logsUrl}`
|
|
1223
|
+
);
|
|
1224
|
+
}).catch((err) => {
|
|
1225
|
+
session.send(
|
|
1226
|
+
`❌ 同步所有页面失败,请前往控制台查看日志:${this.config.logsUrl}`
|
|
1227
|
+
);
|
|
1228
|
+
this.log.error(`同步所有页面失败,错误信息:${err}`);
|
|
1229
|
+
});
|
|
901
1230
|
});
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
);
|
|
907
|
-
await syncPages(ggbot, bwikibot).then(() => {
|
|
908
|
-
session.send(
|
|
909
|
-
`✅ 已尝试同步所有页面,请前往控制台查看:${config.logsUrl}`
|
|
910
|
-
);
|
|
911
|
-
}).catch((err) => {
|
|
1231
|
+
ctx.command("sync.allpages", "同步所有页面", { authority: 2 }).action(async ({ session }) => {
|
|
1232
|
+
if (!this.checkBotsReady(ctx)) {
|
|
1233
|
+
return session.send("❌ Wiki 机器人未就绪,请检查登录配置或查看日志");
|
|
1234
|
+
}
|
|
912
1235
|
session.send(
|
|
913
|
-
|
|
1236
|
+
`🚀 开始同步所有页面,任务耗时较长,请前往控制台查看日志:${this.config.logsUrl}`
|
|
914
1237
|
);
|
|
915
|
-
|
|
1238
|
+
await syncPages(ctx.wikiBot.getGGBot(), ctx.wikiBot.getBWikiBot()).then(() => {
|
|
1239
|
+
session.send(
|
|
1240
|
+
`✅ 已尝试同步所有页面,请前往控制台查看:${this.config.logsUrl}`
|
|
1241
|
+
);
|
|
1242
|
+
}).catch((err) => {
|
|
1243
|
+
session.send(
|
|
1244
|
+
`❌ 同步所有页面失败,请前往控制台查看日志:${this.config.logsUrl}`
|
|
1245
|
+
);
|
|
1246
|
+
this.log.error(`同步所有页面失败,错误信息:${err}`);
|
|
1247
|
+
});
|
|
916
1248
|
});
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
session.send(
|
|
924
|
-
`✅
|
|
1249
|
+
ctx.command("sync.module <moduleTitle:string>", "同步指定模块", {
|
|
1250
|
+
authority: 2
|
|
1251
|
+
}).action(async ({ session }, moduleTitle) => {
|
|
1252
|
+
if (!this.checkBotsReady(ctx)) {
|
|
1253
|
+
return session.send("❌ Wiki 机器人未就绪,请检查登录配置或查看日志");
|
|
1254
|
+
}
|
|
1255
|
+
await session.send(
|
|
1256
|
+
`✅ 同步中,请前往控制台查看:${this.config.logsUrl}`
|
|
925
1257
|
);
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
1258
|
+
await syncSingleModule(
|
|
1259
|
+
ctx.wikiBot.getGGBot(),
|
|
1260
|
+
ctx.wikiBot.getBWikiBot(),
|
|
1261
|
+
moduleTitle,
|
|
1262
|
+
"sync-bot"
|
|
1263
|
+
).then(() => {
|
|
1264
|
+
session.send(
|
|
1265
|
+
`✅ 已尝试同步模块:${moduleTitle},请前往控制台查看:${this.config.logsUrl}`
|
|
1266
|
+
);
|
|
1267
|
+
}).catch((err) => {
|
|
1268
|
+
session.send(`❌ 同步模块失败:${moduleTitle}`);
|
|
1269
|
+
this.log.error(`错误信息:${err}`);
|
|
1270
|
+
});
|
|
929
1271
|
});
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
session.send(
|
|
937
|
-
`✅ 已尝试同步所有模块,请前往控制台查看:${config.logsUrl}`
|
|
938
|
-
);
|
|
939
|
-
}).catch((err) => {
|
|
940
|
-
session.send(
|
|
941
|
-
`❌ 同步所有模块失败,请前往控制台查看日志:${config.logsUrl}`
|
|
1272
|
+
ctx.command("sync.allmodules", "同步所有模块", { authority: 2 }).action(async ({ session }) => {
|
|
1273
|
+
if (!this.checkBotsReady(ctx)) {
|
|
1274
|
+
return session.send("❌ Wiki 机器人未就绪,请检查登录配置或查看日志");
|
|
1275
|
+
}
|
|
1276
|
+
await session.send(
|
|
1277
|
+
`🚀 开始同步所有模块,任务耗时较长,请前往控制台查看:${this.config.logsUrl}`
|
|
942
1278
|
);
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
`${imgTitle.startsWith("File:") ? "" : "File:"}${imgTitle}`,
|
|
954
|
-
config
|
|
955
|
-
).then(() => {
|
|
956
|
-
session.send(`✅ 已尝试同步图片:${imgTitle}`);
|
|
957
|
-
}).catch((err) => {
|
|
958
|
-
session.send(`❌ 同步图片失败:${imgTitle}`);
|
|
959
|
-
log.error(`同步图片失败:${imgTitle},错误信息:${err}`);
|
|
1279
|
+
await syncModules(ctx.wikiBot.getGGBot(), ctx.wikiBot.getBWikiBot()).then(() => {
|
|
1280
|
+
session.send(
|
|
1281
|
+
`✅ 已尝试同步所有模块,请前往控制台查看:${this.config.logsUrl}`
|
|
1282
|
+
);
|
|
1283
|
+
}).catch((err) => {
|
|
1284
|
+
session.send(
|
|
1285
|
+
`❌ 同步所有模块失败,请前往控制台查看日志:${this.config.logsUrl}`
|
|
1286
|
+
);
|
|
1287
|
+
this.log.error(`同步所有模块失败,错误信息:${err}`);
|
|
1288
|
+
});
|
|
960
1289
|
});
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
session.send(
|
|
968
|
-
`✅ 已尝试同步所有图片,请前往控制台查看:${config.logsUrl}`
|
|
1290
|
+
ctx.command("sync.img <imgTitle:string>", "同步指定图片", { authority: 2 }).action(async ({ session }, imgTitle) => {
|
|
1291
|
+
if (!this.checkBotsReady(ctx)) {
|
|
1292
|
+
return session.send("❌ Wiki 机器人未就绪,请检查登录配置或查看日志");
|
|
1293
|
+
}
|
|
1294
|
+
await session.send(
|
|
1295
|
+
`🚀 开始同步,任务可能耗时较长,请前往控制台查看:${this.config.logsUrl}`
|
|
969
1296
|
);
|
|
970
|
-
|
|
1297
|
+
await syncSingleImage(
|
|
1298
|
+
ctx.wikiBot.getGGBot(),
|
|
1299
|
+
ctx.wikiBot.getBWikiBot(),
|
|
1300
|
+
`${imgTitle.startsWith("File:") ? "" : "File:"}${imgTitle}`,
|
|
1301
|
+
this.config
|
|
1302
|
+
).then(() => {
|
|
1303
|
+
session.send(`✅ 已尝试同步图片:${imgTitle}`);
|
|
1304
|
+
}).catch((err) => {
|
|
1305
|
+
session.send(`❌ 同步图片失败:${imgTitle}`);
|
|
1306
|
+
this.log.error(`同步图片失败:${imgTitle},错误信息:${err}`);
|
|
1307
|
+
});
|
|
1308
|
+
});
|
|
1309
|
+
ctx.command("sync.allimgs", "同步所有图片", { authority: 2 }).action(async ({ session }) => {
|
|
1310
|
+
if (!this.checkBotsReady(ctx)) {
|
|
1311
|
+
return session.send("❌ Wiki 机器人未就绪,请检查登录配置或查看日志");
|
|
1312
|
+
}
|
|
971
1313
|
session.send(
|
|
972
|
-
|
|
1314
|
+
`🚀 开始同步所有图片,任务耗时较长,请前往控制台查看:${this.config.logsUrl}`
|
|
973
1315
|
);
|
|
974
|
-
|
|
1316
|
+
await syncAllImages(
|
|
1317
|
+
ctx.wikiBot.getGGBot(),
|
|
1318
|
+
ctx.wikiBot.getBWikiBot(),
|
|
1319
|
+
this.config
|
|
1320
|
+
).then(() => {
|
|
1321
|
+
session.send(
|
|
1322
|
+
`✅ 已尝试同步所有图片,请前往控制台查看:${this.config.logsUrl}`
|
|
1323
|
+
);
|
|
1324
|
+
}).catch((err) => {
|
|
1325
|
+
session.send(
|
|
1326
|
+
`❌ 同步所有图片失败,请前往控制台查看日志:${this.config.logsUrl}`
|
|
1327
|
+
);
|
|
1328
|
+
this.log.error(`同步所有图片失败,错误信息:${err}`);
|
|
1329
|
+
});
|
|
975
1330
|
});
|
|
1331
|
+
}
|
|
1332
|
+
};
|
|
1333
|
+
((SyncCommands2) => {
|
|
1334
|
+
SyncCommands2.Config = import_koishi8.Schema.object({
|
|
1335
|
+
ggUsername: import_koishi8.Schema.string().description("WIKIGG 用户名").default("1"),
|
|
1336
|
+
ggPassword: import_koishi8.Schema.string().description("WIKIGG 密码").default("1"),
|
|
1337
|
+
bwikiusername: import_koishi8.Schema.string().description("bwiki用户名").default("1"),
|
|
1338
|
+
bwikipassword: import_koishi8.Schema.string().description("bwiki密码").default("1"),
|
|
1339
|
+
domain: import_koishi8.Schema.string().description("你的短链域名(必填,如:klei.vip)").default("klei.vip"),
|
|
1340
|
+
main_site: import_koishi8.Schema.string().description("主站域名(必填,如:oxygennotincluded.wiki.gg)").default("oxygennotincluded.wiki.gg/zh"),
|
|
1341
|
+
bwiki_site: import_koishi8.Schema.string().description("镜像站域名(必填,如:wiki.biligame.com)").default("wiki.biligame.com/oni"),
|
|
1342
|
+
logsUrl: import_koishi8.Schema.string().description("日志查看地址").default("https://klei.vip/onilogs")
|
|
976
1343
|
});
|
|
977
|
-
|
|
978
|
-
const queryKey = itemName.trim().toLowerCase();
|
|
979
|
-
if (queryKey === "")
|
|
980
|
-
return `以下是使用说明:
|
|
981
|
-
原站点: https://${config.domain}/gg/88888888
|
|
1344
|
+
})(SyncCommands || (SyncCommands = {}));
|
|
982
1345
|
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1346
|
+
// src/plugins/queryCommands.ts
|
|
1347
|
+
var import_koishi9 = require("koishi");
|
|
1348
|
+
var SPECIAL_CASES = /* @__PURE__ */ new Map([
|
|
1349
|
+
[
|
|
1350
|
+
"火箭计算器",
|
|
1351
|
+
"请前往以下站点使用火箭计算器工具:\n\nhttps://klei.vip/calculator\n\n(注:该工具正在测试阶段,数据可能不够准确,仅供参考)"
|
|
1352
|
+
]
|
|
1353
|
+
]);
|
|
1354
|
+
var QueryCommands = class {
|
|
1355
|
+
static {
|
|
1356
|
+
__name(this, "QueryCommands");
|
|
1357
|
+
}
|
|
1358
|
+
static inject = ["database"];
|
|
1359
|
+
config;
|
|
1360
|
+
constructor(ctx, config) {
|
|
1361
|
+
this.config = config;
|
|
1362
|
+
this.registerCommands(ctx);
|
|
1363
|
+
}
|
|
1364
|
+
registerCommands(ctx) {
|
|
1365
|
+
ctx.command("x <itemName>", "查询缺氧中文wiki,精准匹配+拼音模糊匹配").alias("/查wiki").action(async ({ session }, itemName = "") => {
|
|
1366
|
+
const queryKey = itemName.trim().toLowerCase();
|
|
1367
|
+
if (!queryKey) {
|
|
1368
|
+
return this.getUsageMessage();
|
|
1369
|
+
}
|
|
1370
|
+
if (SPECIAL_CASES.has(queryKey)) {
|
|
1371
|
+
return SPECIAL_CASES.get(queryKey);
|
|
1372
|
+
}
|
|
1373
|
+
const { pinyin_full: queryPinyinFull, pinyin_first: queryPinyinFirst } = generatePinyinInfo(queryKey);
|
|
1374
|
+
const preciseMatch = await this.findPreciseMatch(
|
|
1375
|
+
ctx,
|
|
1376
|
+
queryKey,
|
|
1377
|
+
queryPinyinFull,
|
|
1378
|
+
queryPinyinFirst
|
|
1379
|
+
);
|
|
1380
|
+
if (preciseMatch) {
|
|
1381
|
+
return this.formatResultMessage(
|
|
1382
|
+
preciseMatch,
|
|
1383
|
+
preciseMatch.prefix
|
|
1384
|
+
);
|
|
1385
|
+
}
|
|
1386
|
+
const allPages = await ctx.database.get("wikipages", {});
|
|
1387
|
+
if (allPages.length === 0) {
|
|
1388
|
+
return `❌ 本地缓存为空,请联系管理员执行【update】指令更新缓存!`;
|
|
1389
|
+
}
|
|
1390
|
+
const fuzzyMatches = this.findFuzzyMatches(
|
|
1391
|
+
allPages,
|
|
1392
|
+
queryKey,
|
|
1393
|
+
queryPinyinFull,
|
|
1394
|
+
queryPinyinFirst
|
|
1395
|
+
);
|
|
1396
|
+
if (fuzzyMatches.length === 0) {
|
|
1397
|
+
return `❌ 未找到【${queryKey}】相关内容,请按游戏内标准名称重新查询!`;
|
|
1398
|
+
}
|
|
1399
|
+
return await this.handleSelection(session, fuzzyMatches);
|
|
1000
1400
|
});
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
原站点: https://${config.domain}/gg
|
|
1401
|
+
}
|
|
1402
|
+
getUsageMessage() {
|
|
1403
|
+
return `以下是使用说明:
|
|
1404
|
+
原站点: https://${this.config.domain}/gg/88888888
|
|
1005
1405
|
|
|
1006
|
-
bwiki: https://${config.domain}/bw
|
|
1406
|
+
bwiki: https://${this.config.domain}/bw/88888888`;
|
|
1407
|
+
}
|
|
1408
|
+
formatResultMessage(match, prefix) {
|
|
1409
|
+
let message = "";
|
|
1410
|
+
if (prefix) {
|
|
1411
|
+
message += prefix + "\n";
|
|
1007
1412
|
}
|
|
1008
|
-
|
|
1009
|
-
pinyin_first: queryKey
|
|
1010
|
-
});
|
|
1011
|
-
if (preciseFirstPinyinRes.length > 0) {
|
|
1012
|
-
const { id: id2, title } = preciseFirstPinyinRes[0];
|
|
1013
|
-
return `✅ 首字母精准匹配成功(${queryKey} → ${title})
|
|
1014
|
-
原站点: https://${config.domain}/gg/${id2}
|
|
1413
|
+
message += `原站点: https://${this.config.domain}/gg/${match.id}
|
|
1015
1414
|
|
|
1016
|
-
bwiki: https://${config.domain}/bw/${
|
|
1415
|
+
bwiki: https://${this.config.domain}/bw/${match.id}`;
|
|
1416
|
+
return message;
|
|
1417
|
+
}
|
|
1418
|
+
async findPreciseMatch(ctx, queryKey, queryPinyinFull, queryPinyinFirst) {
|
|
1419
|
+
const checks = [
|
|
1420
|
+
{ query: { title: queryKey }, prefix: "✅ 精准匹配成功" },
|
|
1421
|
+
{
|
|
1422
|
+
query: { pinyin_full: queryKey },
|
|
1423
|
+
prefix: `✅ 拼音精准匹配成功(${queryKey} → `
|
|
1424
|
+
},
|
|
1425
|
+
{
|
|
1426
|
+
query: { pinyin_first: queryKey },
|
|
1427
|
+
prefix: `✅ 首字母精准匹配成功(${queryKey} → `
|
|
1428
|
+
}
|
|
1429
|
+
];
|
|
1430
|
+
for (const check of checks) {
|
|
1431
|
+
const results = await ctx.database.get("wikipages", check.query);
|
|
1432
|
+
if (results.length > 0) {
|
|
1433
|
+
const match = results[0];
|
|
1434
|
+
let prefix = check.prefix;
|
|
1435
|
+
if (prefix && prefix.includes("→")) {
|
|
1436
|
+
prefix += `${match.title})`;
|
|
1437
|
+
}
|
|
1438
|
+
match.prefix = prefix;
|
|
1439
|
+
return match;
|
|
1440
|
+
}
|
|
1017
1441
|
}
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1442
|
+
return null;
|
|
1443
|
+
}
|
|
1444
|
+
calculateScore(page, queryKey, queryPinyinFull, queryPinyinFirst) {
|
|
1445
|
+
let score = 0;
|
|
1446
|
+
const { title, pinyin_full, pinyin_first } = page;
|
|
1447
|
+
if (title.includes(queryKey)) score += 10;
|
|
1448
|
+
if (pinyin_full.startsWith(queryPinyinFull)) score += 9;
|
|
1449
|
+
if (pinyin_full.includes(queryPinyinFull)) score += 8;
|
|
1450
|
+
if (pinyin_first.includes(queryPinyinFirst)) score += 6;
|
|
1451
|
+
if (queryPinyinFull.includes(
|
|
1452
|
+
pinyin_full.substring(
|
|
1453
|
+
0,
|
|
1454
|
+
Math.min(pinyin_full.length, queryPinyinFull.length)
|
|
1455
|
+
)
|
|
1456
|
+
)) {
|
|
1457
|
+
score += 5;
|
|
1021
1458
|
}
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
Math.min(pinyin_full.length, queryPinyinFull.length)
|
|
1034
|
-
)
|
|
1035
|
-
))
|
|
1036
|
-
score += 5;
|
|
1459
|
+
return score;
|
|
1460
|
+
}
|
|
1461
|
+
findFuzzyMatches(allPages, queryKey, queryPinyinFull, queryPinyinFirst) {
|
|
1462
|
+
const matchResults = [];
|
|
1463
|
+
for (const page of allPages) {
|
|
1464
|
+
const score = this.calculateScore(
|
|
1465
|
+
page,
|
|
1466
|
+
queryKey,
|
|
1467
|
+
queryPinyinFull,
|
|
1468
|
+
queryPinyinFirst
|
|
1469
|
+
);
|
|
1037
1470
|
if (score > 0) {
|
|
1038
|
-
|
|
1471
|
+
matchResults.push({ id: page.id, title: page.title, score });
|
|
1039
1472
|
}
|
|
1040
|
-
});
|
|
1041
|
-
if (matchResult.length === 0) {
|
|
1042
|
-
return `❌ 未找到【${queryKey}】相关内容,请按游戏内标准名称重新查询!`;
|
|
1043
1473
|
}
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
return a.title.length - b.title.length;
|
|
1047
|
-
});
|
|
1048
|
-
const uniqueResult = Array.from(
|
|
1049
|
-
new Map(sortedResult.map((item) => [item.title, item])).values()
|
|
1474
|
+
return matchResults.sort((a, b) => b.score - a.score || a.title.length - b.title.length).filter(
|
|
1475
|
+
(item, index, array) => array.findIndex((t) => t.title === item.title) === index
|
|
1050
1476
|
).slice(0, 5);
|
|
1051
|
-
|
|
1477
|
+
}
|
|
1478
|
+
async handleSelection(session, matches) {
|
|
1479
|
+
const resultCount = matches.length;
|
|
1052
1480
|
let replyMsg = `🔍 未找到精准匹配,为你找到【 ${resultCount} 】个相似结果,请输入序号选择(10秒内有效):
|
|
1053
1481
|
`;
|
|
1054
|
-
|
|
1482
|
+
matches.forEach((item, index) => {
|
|
1055
1483
|
replyMsg += `${index + 1}. ${item.title}
|
|
1056
1484
|
`;
|
|
1057
1485
|
});
|
|
@@ -1060,85 +1488,163 @@ bwiki: https://${config.domain}/bw/${id2} `;
|
|
|
1060
1488
|
await session.send(replyMsg);
|
|
1061
1489
|
const userInput = await session.prompt(15e3);
|
|
1062
1490
|
if (!userInput) return;
|
|
1063
|
-
const selectNum = parseInt(userInput.trim());
|
|
1491
|
+
const selectNum = parseInt(userInput.trim(), 10);
|
|
1064
1492
|
if (isNaN(selectNum) || selectNum < 1 || selectNum > resultCount) {
|
|
1065
1493
|
return `❌ 输入无效!请输入 1-${resultCount} 之间的数字序号`;
|
|
1066
1494
|
}
|
|
1067
|
-
const
|
|
1068
|
-
return
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1495
|
+
const selected = matches[selectNum - 1];
|
|
1496
|
+
return this.formatResultMessage(
|
|
1497
|
+
selected,
|
|
1498
|
+
"✅ 选择成功"
|
|
1499
|
+
);
|
|
1500
|
+
}
|
|
1501
|
+
};
|
|
1502
|
+
((QueryCommands2) => {
|
|
1503
|
+
QueryCommands2.Config = import_koishi9.Schema.object({
|
|
1504
|
+
domain: import_koishi9.Schema.string().description("你的短链域名(必填,如:klei.vip)").default("klei.vip")
|
|
1072
1505
|
});
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1506
|
+
})(QueryCommands || (QueryCommands = {}));
|
|
1507
|
+
|
|
1508
|
+
// src/plugins/updateCommands.ts
|
|
1509
|
+
var import_koishi10 = require("koishi");
|
|
1510
|
+
var UpdateCommands = class {
|
|
1511
|
+
static {
|
|
1512
|
+
__name(this, "UpdateCommands");
|
|
1513
|
+
}
|
|
1514
|
+
static inject = ["database", "wikiBot"];
|
|
1515
|
+
config;
|
|
1516
|
+
log;
|
|
1517
|
+
constructor(ctx, config) {
|
|
1518
|
+
this.config = config;
|
|
1519
|
+
this.log = ctx.logger("oni-sync");
|
|
1520
|
+
this.registerCommands(ctx);
|
|
1521
|
+
}
|
|
1522
|
+
registerCommands(ctx) {
|
|
1523
|
+
ctx.command("update", "更新本地页面缓存(主站)", { authority: 2 }).action(async ({ session }) => {
|
|
1524
|
+
await session.execute("update.status");
|
|
1525
|
+
try {
|
|
1526
|
+
const res = await ctx.wikiBot.getGGBot().request({
|
|
1527
|
+
action: "query",
|
|
1528
|
+
list: "allpages",
|
|
1529
|
+
format: "json",
|
|
1530
|
+
aplimit: "max"
|
|
1531
|
+
});
|
|
1532
|
+
logger.info("主站页面查询成功");
|
|
1533
|
+
const pages = res.query.allpages || [];
|
|
1534
|
+
const pageData = pages.map((page) => {
|
|
1535
|
+
const { pinyin_full, pinyin_first } = generatePinyinInfo(
|
|
1536
|
+
page.title
|
|
1537
|
+
);
|
|
1538
|
+
return {
|
|
1539
|
+
id: page.pageid,
|
|
1540
|
+
title: page.title,
|
|
1541
|
+
pinyin_full,
|
|
1542
|
+
pinyin_first
|
|
1543
|
+
};
|
|
1544
|
+
});
|
|
1545
|
+
if (pageData.length > 0) {
|
|
1546
|
+
await ctx.database.upsert("wikipages", pageData);
|
|
1547
|
+
}
|
|
1548
|
+
session.send(`✅ 检索到 ${pages.length} 个页面,已更新至数据库`);
|
|
1549
|
+
logger.info(`检索到 ${pages.length} 个页面,已更新至数据库`);
|
|
1550
|
+
} catch (err) {
|
|
1551
|
+
this.log.error("主站缓存更新失败", err);
|
|
1552
|
+
session.send("❌ 主站缓存更新失败,请联系管理员查看日志");
|
|
1095
1553
|
}
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1554
|
+
});
|
|
1555
|
+
ctx.command("update.delete", "删除本地页面缓存", { authority: 4 }).action(async ({ session }) => {
|
|
1556
|
+
try {
|
|
1557
|
+
const count = await ctx.database.remove("wikipages", {});
|
|
1558
|
+
session.send(`✅ 已删除 ${count.removed} 条本地缓存`);
|
|
1559
|
+
logger.info(`已删除 ${count.removed} 条本地缓存`);
|
|
1560
|
+
} catch (err) {
|
|
1561
|
+
this.log.error("删除缓存失败", err);
|
|
1562
|
+
session.send("❌ 删除缓存失败,请联系管理员查看日志");
|
|
1563
|
+
}
|
|
1564
|
+
});
|
|
1565
|
+
ctx.command("update.status", "查询本地缓存数量", { authority: 1 }).action(async ({ session }) => {
|
|
1566
|
+
try {
|
|
1567
|
+
const pages = await ctx.database.get("wikipages", {});
|
|
1568
|
+
session.send(`📊 数据库中缓存了 ${pages.length} 条页面`);
|
|
1569
|
+
logger.info(`数据库中缓存了 ${pages.length} 条页面`);
|
|
1570
|
+
} catch (err) {
|
|
1571
|
+
this.log.error("查询缓存状态失败", err);
|
|
1572
|
+
session.send("❌ 查询缓存状态失败,请联系管理员查看日志");
|
|
1573
|
+
}
|
|
1574
|
+
});
|
|
1575
|
+
ctx.command("redirect <pageName> <targetPageName>", "添加原站点重定向", {
|
|
1576
|
+
authority: 2
|
|
1577
|
+
}).alias("重定向").action(async ({ session }, pageName, targetPageName) => {
|
|
1578
|
+
if (!pageName || !targetPageName) {
|
|
1579
|
+
return "❌ 参数错误!用法:redirect <原页面名> <目标页面名>";
|
|
1580
|
+
}
|
|
1581
|
+
try {
|
|
1582
|
+
await ctx.wikiBot.getGGBot().create(
|
|
1583
|
+
pageName,
|
|
1584
|
+
`#REDIRECT [[${targetPageName}]]`,
|
|
1585
|
+
"来自qq机器人的添加重定向页面请求"
|
|
1586
|
+
);
|
|
1587
|
+
logger.info(`已为 ${pageName} 添加重定向至 ${targetPageName}`);
|
|
1588
|
+
session.send(`✅ 已尝试添加重定向 ${pageName} -> ${targetPageName}`);
|
|
1589
|
+
await session.execute(`update`);
|
|
1590
|
+
} catch (err) {
|
|
1591
|
+
this.log.error(
|
|
1592
|
+
`添加重定向 ${pageName} -> ${targetPageName} 失败`,
|
|
1593
|
+
err
|
|
1594
|
+
);
|
|
1595
|
+
session.send(`❌ 添加重定向失败,请联系管理员查看日志`);
|
|
1596
|
+
}
|
|
1597
|
+
});
|
|
1598
|
+
ctx.command("relogin", "手动重新登录 Wiki 机器人", { authority: 2 }).alias("重新登录").action(async ({ session }) => {
|
|
1599
|
+
session.send("🚀 开始重新登录 Wiki 机器人...");
|
|
1600
|
+
try {
|
|
1601
|
+
const result = await ctx.wikiBot.relogin();
|
|
1602
|
+
let message = "📋 重新登录结果:\n";
|
|
1603
|
+
message += result.gg ? "✅ WIKIGG 登录成功\n" : "❌ WIKIGG 登录失败\n";
|
|
1604
|
+
message += result.bwiki ? "✅ bwiki 登录成功\n" : "❌ bwiki 登录失败\n";
|
|
1605
|
+
if (result.gg && result.bwiki) {
|
|
1606
|
+
message += "\n🎉 两个 Wiki 机器人都已成功登录!";
|
|
1607
|
+
} else if (result.gg || result.bwiki) {
|
|
1608
|
+
message += "\n⚠️ 部分 Wiki 机器人已登录";
|
|
1609
|
+
} else {
|
|
1610
|
+
message += "\n💥 所有 Wiki 机器人登录都失败了,请检查配置";
|
|
1611
|
+
}
|
|
1612
|
+
session.send(message);
|
|
1613
|
+
} catch (err) {
|
|
1614
|
+
this.log.error("重新登录失败", err);
|
|
1615
|
+
session.send("❌ 重新登录过程中发生错误,请查看日志");
|
|
1616
|
+
}
|
|
1617
|
+
});
|
|
1618
|
+
}
|
|
1619
|
+
};
|
|
1620
|
+
((UpdateCommands2) => {
|
|
1621
|
+
UpdateCommands2.Config = import_koishi10.Schema.object({
|
|
1622
|
+
logsUrl: import_koishi10.Schema.string().description("日志查看地址").default("https://klei.vip/onilogs")
|
|
1122
1623
|
});
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1624
|
+
})(UpdateCommands || (UpdateCommands = {}));
|
|
1625
|
+
|
|
1626
|
+
// src/index.ts
|
|
1627
|
+
var name = "oni-sync-bot";
|
|
1628
|
+
var Config = import_koishi11.Schema.intersect([
|
|
1629
|
+
WikiBotService.Config,
|
|
1630
|
+
RouteRedirect.Config,
|
|
1631
|
+
SyncCommands.Config,
|
|
1632
|
+
QueryCommands.Config,
|
|
1633
|
+
UpdateCommands.Config
|
|
1634
|
+
]);
|
|
1635
|
+
function apply(ctx, config) {
|
|
1636
|
+
ctx.plugin(WikiBotService, config);
|
|
1637
|
+
ctx.plugin(ConsoleLogProvider);
|
|
1638
|
+
ctx.plugin(DatabaseExtension);
|
|
1639
|
+
ctx.plugin(RouteRedirect, config);
|
|
1640
|
+
ctx.plugin(SyncCommands, config);
|
|
1641
|
+
ctx.plugin(QueryCommands, config);
|
|
1642
|
+
ctx.plugin(UpdateCommands, config);
|
|
1643
|
+
ctx.inject(["console"], (ctx2) => {
|
|
1644
|
+
ctx2.console.addEntry({
|
|
1645
|
+
dev: (0, import_path.resolve)(__dirname, "../client/index.ts"),
|
|
1646
|
+
prod: (0, import_path.resolve)(__dirname, "../dist")
|
|
1647
|
+
});
|
|
1142
1648
|
});
|
|
1143
1649
|
}
|
|
1144
1650
|
__name(apply, "apply");
|
|
@@ -1146,6 +1652,5 @@ __name(apply, "apply");
|
|
|
1146
1652
|
0 && (module.exports = {
|
|
1147
1653
|
Config,
|
|
1148
1654
|
apply,
|
|
1149
|
-
inject,
|
|
1150
1655
|
name
|
|
1151
1656
|
});
|