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