koishi-plugin-oni-sync-bot 0.3.4 → 0.4.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/lib/index.d.ts +7 -0
- package/lib/index.js +203 -157
- package/lib/service/logspush.d.ts +16 -0
- package/lib/service/router.d.ts +9 -0
- package/lib/sync/imgSync.d.ts +29 -0
- package/lib/sync/pageSync.d.ts +29 -0
- package/lib/task/sync.d.ts +8 -0
- package/lib/wiki/querywiki.d.ts +19 -0
- package/lib/wiki/wikicore.d.ts +41 -0
- package/package.json +1 -1
package/lib/index.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { Context, Schema } from "koishi";
|
|
2
|
+
export declare const name = "oni-sync-bot";
|
|
3
|
+
export declare const inject: string[];
|
|
4
|
+
export interface Config {
|
|
5
|
+
}
|
|
6
|
+
export declare const Config: Schema<Config>;
|
|
7
|
+
export declare function apply(ctx: Context, config: Config): void;
|
package/lib/index.js
CHANGED
|
@@ -30,17 +30,17 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
30
30
|
// src/index.ts
|
|
31
31
|
var src_exports = {};
|
|
32
32
|
__export(src_exports, {
|
|
33
|
-
Config: () =>
|
|
34
|
-
apply: () =>
|
|
33
|
+
Config: () => Config6,
|
|
34
|
+
apply: () => apply5,
|
|
35
35
|
inject: () => inject,
|
|
36
36
|
name: () => name
|
|
37
37
|
});
|
|
38
38
|
module.exports = __toCommonJS(src_exports);
|
|
39
|
-
var
|
|
39
|
+
var import_koishi10 = require("koishi");
|
|
40
40
|
var import_path = require("path");
|
|
41
|
-
var import_plugin_console = require("@koishijs/plugin-console");
|
|
42
41
|
|
|
43
|
-
// src/
|
|
42
|
+
// src/wiki/wikicore.ts
|
|
43
|
+
var import_koishi2 = require("koishi");
|
|
44
44
|
var import_mwn = require("mwn");
|
|
45
45
|
|
|
46
46
|
// src/utils/tools.ts
|
|
@@ -90,7 +90,28 @@ function generatePinyinInfo(text) {
|
|
|
90
90
|
__name(generatePinyinInfo, "generatePinyinInfo");
|
|
91
91
|
var logger = new import_koishi.Logger("oni-sync");
|
|
92
92
|
|
|
93
|
-
// src/
|
|
93
|
+
// src/wiki/wikicore.ts
|
|
94
|
+
var Config = import_koishi2.Schema.object({
|
|
95
|
+
ggUsername: import_koishi2.Schema.string().description("WIKIGG 用户名").default("1"),
|
|
96
|
+
ggPassword: import_koishi2.Schema.string().description("WIKIGG 密码").default("1"),
|
|
97
|
+
bwikiusername: import_koishi2.Schema.string().description("bwiki用户名").default("1"),
|
|
98
|
+
bwikipassword: import_koishi2.Schema.string().description("bwiki密码").default("1"),
|
|
99
|
+
domain: import_koishi2.Schema.string().description("你的短链域名(必填,如:klei.vip)").default("klei.vip"),
|
|
100
|
+
logsUrl: import_koishi2.Schema.string().description("日志查看地址").default("https://klei.vip/onilogs")
|
|
101
|
+
});
|
|
102
|
+
function apply(ctx, config) {
|
|
103
|
+
const sitesConfig = getSitesConfig(config);
|
|
104
|
+
ctx.on("ready", async () => {
|
|
105
|
+
const wikiggBot = await login(sitesConfig.gg);
|
|
106
|
+
const bwikiBot = await login(sitesConfig.bwiki);
|
|
107
|
+
ctx.wikibot = { wikigg: wikiggBot, bwiki: bwikiBot };
|
|
108
|
+
});
|
|
109
|
+
ctx.on("dispose", () => {
|
|
110
|
+
logger.warn("⚠️ 插件已卸载,ctx.wikibot清除...");
|
|
111
|
+
ctx.wikibot = void 0;
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
__name(apply, "apply");
|
|
94
115
|
async function login(siteConfig) {
|
|
95
116
|
const bot = new import_mwn.Mwn({
|
|
96
117
|
apiUrl: siteConfig.api,
|
|
@@ -117,8 +138,6 @@ async function login(siteConfig) {
|
|
|
117
138
|
return bot;
|
|
118
139
|
}
|
|
119
140
|
__name(login, "login");
|
|
120
|
-
|
|
121
|
-
// src/config/index.ts
|
|
122
141
|
var userAgent = `OniSyncBot/1.0 (https://klei.vip; Charles@klei.vip)`;
|
|
123
142
|
function getSitesConfig(config) {
|
|
124
143
|
return {
|
|
@@ -140,11 +159,85 @@ function getSitesConfig(config) {
|
|
|
140
159
|
}
|
|
141
160
|
__name(getSitesConfig, "getSitesConfig");
|
|
142
161
|
|
|
143
|
-
// src/
|
|
162
|
+
// src/service/logspush.ts
|
|
163
|
+
var import_plugin_console = require("@koishijs/plugin-console");
|
|
144
164
|
var import_koishi3 = require("koishi");
|
|
165
|
+
var Config2 = import_koishi3.Schema.object({
|
|
166
|
+
logsUrl: import_koishi3.Schema.string().description("日志查看地址").default("https://klei.vip/onilogs")
|
|
167
|
+
});
|
|
168
|
+
var logBuffer = [];
|
|
169
|
+
var PublicLogProvider = class extends import_plugin_console.DataService {
|
|
170
|
+
static {
|
|
171
|
+
__name(this, "PublicLogProvider");
|
|
172
|
+
}
|
|
173
|
+
constructor(ctx) {
|
|
174
|
+
super(ctx, "onilogs", { authority: 0 });
|
|
175
|
+
}
|
|
176
|
+
async get() {
|
|
177
|
+
return logBuffer;
|
|
178
|
+
}
|
|
179
|
+
};
|
|
180
|
+
function apply2(ctx, config) {
|
|
181
|
+
ctx.plugin(PublicLogProvider);
|
|
182
|
+
const target = {
|
|
183
|
+
colors: 0,
|
|
184
|
+
record: /* @__PURE__ */ __name((record) => {
|
|
185
|
+
if (record.name !== "oni-sync") return;
|
|
186
|
+
logBuffer.push(record);
|
|
187
|
+
if (logBuffer.length > 30) {
|
|
188
|
+
logBuffer = logBuffer.slice(-30);
|
|
189
|
+
}
|
|
190
|
+
ctx.get("console")?.patch("onilogs", logBuffer);
|
|
191
|
+
}, "record")
|
|
192
|
+
};
|
|
193
|
+
import_koishi3.Logger.targets.push(target);
|
|
194
|
+
ctx.on("dispose", () => {
|
|
195
|
+
const index = import_koishi3.Logger.targets.indexOf(target);
|
|
196
|
+
if (index > -1) import_koishi3.Logger.targets.splice(index, 1);
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
__name(apply2, "apply");
|
|
200
|
+
|
|
201
|
+
// src/service/router.ts
|
|
202
|
+
var import_koishi4 = require("koishi");
|
|
203
|
+
var Config3 = import_koishi4.Schema.object({
|
|
204
|
+
main_site: import_koishi4.Schema.string().description("主站域名(必填,如:oxygennotincluded.wiki.gg)").default("oxygennotincluded.wiki.gg/zh"),
|
|
205
|
+
bwiki_site: import_koishi4.Schema.string().description("镜像站域名(必填,如:wiki.biligame.com)").default("wiki.biligame.com/oni")
|
|
206
|
+
});
|
|
207
|
+
function apply3(ctx, config) {
|
|
208
|
+
ctx.server.get("/gg/:id", async (router) => {
|
|
209
|
+
const pageId = Number(router.params.id);
|
|
210
|
+
if (isNaN(pageId)) return router.body = "❌ 无效的页面ID,必须为数字!";
|
|
211
|
+
const [page] = await ctx.database.get("wikipages", { id: pageId });
|
|
212
|
+
if (!page)
|
|
213
|
+
return router.body = `❌ 未找到ID为【${pageId}】的页面,请联系管理员更新缓存!`;
|
|
214
|
+
const targetUrl = `https://${config.main_site}/${encodeURIComponent(
|
|
215
|
+
page.title
|
|
216
|
+
)}?variant=zh`;
|
|
217
|
+
router.redirect(targetUrl);
|
|
218
|
+
});
|
|
219
|
+
ctx.server.get("/bw/:id", async (router) => {
|
|
220
|
+
const pageId = Number(router.params.id);
|
|
221
|
+
if (isNaN(pageId)) return router.body = "❌ 无效的页面ID,必须为数字!";
|
|
222
|
+
const [page] = await ctx.database.get("wikipages", { id: pageId });
|
|
223
|
+
if (!page)
|
|
224
|
+
return router.body = `❌ 未找到ID为【${pageId}】的页面,请联系管理员更新缓存!`;
|
|
225
|
+
const targetUrl = `https://${config.bwiki_site}/${encodeURIComponent(
|
|
226
|
+
page.title
|
|
227
|
+
)}`;
|
|
228
|
+
router.redirect(targetUrl);
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
__name(apply3, "apply");
|
|
232
|
+
|
|
233
|
+
// src/task/sync.ts
|
|
234
|
+
var import_koishi8 = require("koishi");
|
|
235
|
+
|
|
236
|
+
// src/sync/pageSync.ts
|
|
237
|
+
var import_koishi6 = require("koishi");
|
|
145
238
|
|
|
146
239
|
// src/sync/imgSync.ts
|
|
147
|
-
var
|
|
240
|
+
var import_koishi5 = require("koishi");
|
|
148
241
|
var import_node_fetch = __toESM(require("node-fetch"));
|
|
149
242
|
var import_form_data = __toESM(require("form-data"));
|
|
150
243
|
var CONFIG = {
|
|
@@ -179,7 +272,7 @@ async function getImageInfo(site, fileName) {
|
|
|
179
272
|
}
|
|
180
273
|
}
|
|
181
274
|
__name(getImageInfo, "getImageInfo");
|
|
182
|
-
async function syncSingleImage(sourceBot, targetBot, fileName
|
|
275
|
+
async function syncSingleImage(sourceBot, targetBot, fileName) {
|
|
183
276
|
if (CONFIG.IGNORED_IMAGES.includes(fileName)) {
|
|
184
277
|
logger.info(`[SyncImg] 🚫 图片 ${fileName} 在忽略列表,跳过`);
|
|
185
278
|
return { success: true, reason: "ignored" };
|
|
@@ -273,7 +366,7 @@ async function getAllImages(site) {
|
|
|
273
366
|
return allImages;
|
|
274
367
|
}
|
|
275
368
|
__name(getAllImages, "getAllImages");
|
|
276
|
-
async function syncAllImages(sourceBot, targetBot
|
|
369
|
+
async function syncAllImages(sourceBot, targetBot) {
|
|
277
370
|
try {
|
|
278
371
|
const imageList = await getAllImages(sourceBot);
|
|
279
372
|
if (imageList.length === 0) {
|
|
@@ -294,22 +387,17 @@ async function syncAllImages(sourceBot, targetBot, config) {
|
|
|
294
387
|
`
|
|
295
388
|
[SyncAllImg] 📈 进度 ${i + 1}/${imageList.length} (${progress.toFixed(1)}%)`
|
|
296
389
|
);
|
|
297
|
-
const result = await syncSingleImage(
|
|
298
|
-
sourceBot,
|
|
299
|
-
targetBot,
|
|
300
|
-
fileName,
|
|
301
|
-
config
|
|
302
|
-
);
|
|
390
|
+
const result = await syncSingleImage(sourceBot, targetBot, fileName);
|
|
303
391
|
if (!result.success) {
|
|
304
392
|
failCount++;
|
|
305
393
|
failedImages.push(fileName);
|
|
306
|
-
await (0,
|
|
394
|
+
await (0, import_koishi5.sleep)(CONFIG.SYNC_INTERVAL_FAILED);
|
|
307
395
|
} else {
|
|
308
396
|
successCount++;
|
|
309
397
|
if (result.reason === "ignored" || result.reason === "no_change") {
|
|
310
398
|
skipCount++;
|
|
311
399
|
}
|
|
312
|
-
await (0,
|
|
400
|
+
await (0, import_koishi5.sleep)(CONFIG.SYNC_INTERVAL_SUCCESS);
|
|
313
401
|
}
|
|
314
402
|
}
|
|
315
403
|
if (failedImages.length > 0) {
|
|
@@ -321,12 +409,7 @@ async function syncAllImages(sourceBot, targetBot, config) {
|
|
|
321
409
|
for (const fileName of failedImages) {
|
|
322
410
|
logger.info(`
|
|
323
411
|
[SyncAllImg] 🔁 重试: ${fileName}`);
|
|
324
|
-
const result = await syncSingleImage(
|
|
325
|
-
sourceBot,
|
|
326
|
-
targetBot,
|
|
327
|
-
fileName,
|
|
328
|
-
config
|
|
329
|
-
);
|
|
412
|
+
const result = await syncSingleImage(sourceBot, targetBot, fileName);
|
|
330
413
|
if (result.success) {
|
|
331
414
|
successCount++;
|
|
332
415
|
failCount--;
|
|
@@ -335,7 +418,7 @@ async function syncAllImages(sourceBot, targetBot, config) {
|
|
|
335
418
|
stillFailed.push(fileName);
|
|
336
419
|
logger.info(`[SyncAllImg] ❌ 重试失败: ${fileName}`);
|
|
337
420
|
}
|
|
338
|
-
await (0,
|
|
421
|
+
await (0, import_koishi5.sleep)(CONFIG.SYNC_INTERVAL_SUCCESS);
|
|
339
422
|
}
|
|
340
423
|
if (stillFailed.length > 0) {
|
|
341
424
|
logger.info(`
|
|
@@ -422,13 +505,13 @@ async function processPageWithStats(oldSite, newSite, pageTitle, user, stats, fa
|
|
|
422
505
|
if (!syncResult.success) {
|
|
423
506
|
stats.failCount++;
|
|
424
507
|
failedPages.push(pageTitle);
|
|
425
|
-
await (0,
|
|
508
|
+
await (0, import_koishi6.sleep)(CONFIG2.SYNC_INTERVAL_FAILED);
|
|
426
509
|
} else {
|
|
427
510
|
stats.successCount++;
|
|
428
511
|
if (syncResult.reason === "ignored" || syncResult.reason === "no_change") {
|
|
429
512
|
stats.skipCount++;
|
|
430
513
|
}
|
|
431
|
-
await (0,
|
|
514
|
+
await (0, import_koishi6.sleep)(CONFIG2.SYNC_INTERVAL_SUCCESS);
|
|
432
515
|
}
|
|
433
516
|
}
|
|
434
517
|
__name(processPageWithStats, "processPageWithStats");
|
|
@@ -504,11 +587,11 @@ async function syncPages(oldSite, newSite) {
|
|
|
504
587
|
stats.skipCount++;
|
|
505
588
|
}
|
|
506
589
|
logger.info(`[SyncAllPages] ✅ 页面 ${pageTitle} 重试成功`);
|
|
507
|
-
await (0,
|
|
590
|
+
await (0, import_koishi6.sleep)(CONFIG2.SYNC_INTERVAL_SUCCESS);
|
|
508
591
|
} else {
|
|
509
592
|
stillFailed.push(pageTitle);
|
|
510
593
|
logger.info(`[SyncAllPages] ❌ 页面 ${pageTitle} 再次失败`);
|
|
511
|
-
await (0,
|
|
594
|
+
await (0, import_koishi6.sleep)(CONFIG2.SYNC_INTERVAL_FAILED);
|
|
512
595
|
}
|
|
513
596
|
}
|
|
514
597
|
}
|
|
@@ -525,7 +608,7 @@ async function syncPages(oldSite, newSite) {
|
|
|
525
608
|
}
|
|
526
609
|
}
|
|
527
610
|
__name(syncPages, "syncPages");
|
|
528
|
-
async function incrementalUpdate(oldSite, newSite
|
|
611
|
+
async function incrementalUpdate(oldSite, newSite) {
|
|
529
612
|
try {
|
|
530
613
|
const now = /* @__PURE__ */ new Date();
|
|
531
614
|
const threeHoursAgo = new Date(now.getTime() - 3 * 60 * 60 * 1e3);
|
|
@@ -568,7 +651,7 @@ async function incrementalUpdate(oldSite, newSite, config) {
|
|
|
568
651
|
logger.info(
|
|
569
652
|
`[增量更新流程] 🖼️ 检查到图片: ${title},正在尝试转存`
|
|
570
653
|
);
|
|
571
|
-
await syncSingleImage(oldSite, newSite, fileName
|
|
654
|
+
await syncSingleImage(oldSite, newSite, fileName);
|
|
572
655
|
} else {
|
|
573
656
|
await syncSinglePage(
|
|
574
657
|
oldSite,
|
|
@@ -577,11 +660,11 @@ async function incrementalUpdate(oldSite, newSite, config) {
|
|
|
577
660
|
CONFIG2.INCREMENTAL_USER
|
|
578
661
|
);
|
|
579
662
|
}
|
|
580
|
-
await (0,
|
|
663
|
+
await (0, import_koishi6.sleep)(CONFIG2.SYNC_INTERVAL_SUCCESS);
|
|
581
664
|
} catch (error) {
|
|
582
665
|
const errMsg = error instanceof Error ? error.message : String(error);
|
|
583
666
|
logger.error(`[增量更新流程] ❌ 处理 ${title} 时出错:`, errMsg);
|
|
584
|
-
await (0,
|
|
667
|
+
await (0, import_koishi6.sleep)(CONFIG2.SYNC_INTERVAL_FAILED);
|
|
585
668
|
}
|
|
586
669
|
}
|
|
587
670
|
}
|
|
@@ -596,7 +679,7 @@ async function incrementalUpdate(oldSite, newSite, config) {
|
|
|
596
679
|
__name(incrementalUpdate, "incrementalUpdate");
|
|
597
680
|
|
|
598
681
|
// src/sync/moduleSync.ts
|
|
599
|
-
var
|
|
682
|
+
var import_koishi7 = require("koishi");
|
|
600
683
|
var CONFIG3 = {
|
|
601
684
|
MODLE_NAMESPACE: 828,
|
|
602
685
|
// 模块命名空间 (注意:这里原代码拼写为 MODLE,保留原样)
|
|
@@ -700,13 +783,13 @@ async function syncModules(oldSite, newSite) {
|
|
|
700
783
|
if (!syncResult.success) {
|
|
701
784
|
failCount++;
|
|
702
785
|
failedModules.push(moduleTitle);
|
|
703
|
-
await (0,
|
|
786
|
+
await (0, import_koishi7.sleep)(CONFIG3.SYNC_INTERVAL_FAILED);
|
|
704
787
|
} else {
|
|
705
788
|
successCount++;
|
|
706
789
|
if (syncResult.reason === "ignored" || syncResult.reason === "no_change") {
|
|
707
790
|
skipCount++;
|
|
708
791
|
}
|
|
709
|
-
await (0,
|
|
792
|
+
await (0, import_koishi7.sleep)(CONFIG3.SYNC_INTERVAL_SUCCESS);
|
|
710
793
|
}
|
|
711
794
|
}
|
|
712
795
|
if (failedModules.length > 0) {
|
|
@@ -731,11 +814,11 @@ async function syncModules(oldSite, newSite) {
|
|
|
731
814
|
skipCount++;
|
|
732
815
|
}
|
|
733
816
|
logger.info(`[SyncAllModules] ✅ 模块 ${moduleTitle} 重试成功`);
|
|
734
|
-
await (0,
|
|
817
|
+
await (0, import_koishi7.sleep)(CONFIG3.SYNC_INTERVAL_SUCCESS);
|
|
735
818
|
} else {
|
|
736
819
|
stillFailed.push(moduleTitle);
|
|
737
820
|
logger.info(`[SyncAllModules] ❌ 模块 ${moduleTitle} 再次失败`);
|
|
738
|
-
await (0,
|
|
821
|
+
await (0, import_koishi7.sleep)(CONFIG3.SYNC_INTERVAL_FAILED);
|
|
739
822
|
}
|
|
740
823
|
}
|
|
741
824
|
logger.info(`
|
|
@@ -761,135 +844,41 @@ async function syncModules(oldSite, newSite) {
|
|
|
761
844
|
}
|
|
762
845
|
__name(syncModules, "syncModules");
|
|
763
846
|
|
|
764
|
-
// src/
|
|
765
|
-
var
|
|
766
|
-
|
|
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")
|
|
847
|
+
// src/task/sync.ts
|
|
848
|
+
var Config4 = import_koishi8.Schema.object({
|
|
849
|
+
logsUrl: import_koishi8.Schema.string().description("日志查看地址").default("https://klei.vip/onilogs")
|
|
777
850
|
});
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
__name(this, "PublicLogProvider");
|
|
781
|
-
}
|
|
782
|
-
constructor(ctx) {
|
|
783
|
-
super(ctx, "onilogs", { authority: 0 });
|
|
784
|
-
}
|
|
785
|
-
async get() {
|
|
786
|
-
return logBuffer;
|
|
787
|
-
}
|
|
788
|
-
};
|
|
789
|
-
function apply(ctx, config) {
|
|
790
|
-
const log = ctx.logger("oni-sync");
|
|
791
|
-
let ggbot;
|
|
792
|
-
let bwikibot;
|
|
793
|
-
ctx.inject(["console"], (ctx2) => {
|
|
794
|
-
ctx2.console.addEntry({
|
|
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
|
-
});
|
|
851
|
+
function apply4(ctx, config) {
|
|
852
|
+
const log = ctx.logger("sync-task");
|
|
846
853
|
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
|
-
}
|
|
854
|
+
logger.info("定时同步任务已准备就绪");
|
|
856
855
|
ctx.cron("15 * * * *", async () => {
|
|
857
|
-
await incrementalUpdate(
|
|
856
|
+
await incrementalUpdate(ctx.wikibot.wikigg, ctx.wikibot.bwiki);
|
|
858
857
|
});
|
|
859
858
|
ctx.cron("30 8 * * 4", async () => {
|
|
860
|
-
await syncPages(
|
|
859
|
+
await syncPages(ctx.wikibot.wikigg, ctx.wikibot.bwiki).then(() => {
|
|
861
860
|
logger.info("自动任务:尝试同步所有页面,从 WIKIGG 到 bwiki");
|
|
862
861
|
}).catch((err) => {
|
|
863
862
|
logger.error(`同步所有页面失败`);
|
|
864
|
-
|
|
863
|
+
ctx.logger.error(`,错误信息:${err}`);
|
|
865
864
|
});
|
|
866
865
|
});
|
|
867
866
|
ctx.cron("30 8 * * 3", async () => {
|
|
868
|
-
await syncAllImages(
|
|
867
|
+
await syncAllImages(ctx.wikibot.wikigg, ctx.wikibot.bwiki).then(() => {
|
|
869
868
|
logger.info("自动任务:尝试同步所有图片,从 WIKIGG 到 bwiki");
|
|
870
869
|
}).catch((err) => {
|
|
871
870
|
logger.error(`同步所有图片失败`);
|
|
872
|
-
|
|
871
|
+
ctx.logger.error(`,错误信息:${err}`);
|
|
873
872
|
});
|
|
874
873
|
});
|
|
875
874
|
});
|
|
876
|
-
ctx.command("sync <pageTitle:string>", "同步指定页面", { authority: 2 }).action(async ({ session }, pageTitle) => {
|
|
877
|
-
await syncSinglePage(ggbot, bwikibot, pageTitle, "sync-bot").then(() => {
|
|
878
|
-
session.send(
|
|
879
|
-
`✅ 已尝试同步页面:${pageTitle},请前往控制台查看:${config.logsUrl}`
|
|
880
|
-
);
|
|
881
|
-
}).catch((err) => {
|
|
882
|
-
session.send(`❌ 同步页面失败:${pageTitle}`);
|
|
883
|
-
log.error(`,错误信息:${err}`);
|
|
884
|
-
});
|
|
885
|
-
});
|
|
886
875
|
ctx.command("sync.incrementalUpdate", "获取3h内的编辑并尝试更新", {
|
|
887
876
|
authority: 2
|
|
888
877
|
}).alias("增量更新").action(async ({ session }) => {
|
|
889
878
|
session.send(
|
|
890
879
|
`🚀 获取3h内的编辑并尝试更新,任务耗时可能较长,请前往控制台查看日志:${config.logsUrl}`
|
|
891
880
|
);
|
|
892
|
-
await incrementalUpdate(
|
|
881
|
+
await incrementalUpdate(ctx.wikibot.wikigg, ctx.wikibot.bwiki).then(() => {
|
|
893
882
|
session.send(
|
|
894
883
|
`✅ 已尝试获取三小时前的编辑并同步,请前往控制台查看:${config.logsUrl}`
|
|
895
884
|
);
|
|
@@ -904,7 +893,7 @@ function apply(ctx, config) {
|
|
|
904
893
|
session.send(
|
|
905
894
|
`🚀 开始同步所有页面,任务耗时较长,请前往控制台查看日志:${config.logsUrl}`
|
|
906
895
|
);
|
|
907
|
-
await syncPages(
|
|
896
|
+
await syncPages(ctx.wikibot.wikigg, ctx.wikibot.bwiki).then(() => {
|
|
908
897
|
session.send(
|
|
909
898
|
`✅ 已尝试同步所有页面,请前往控制台查看:${config.logsUrl}`
|
|
910
899
|
);
|
|
@@ -919,7 +908,12 @@ function apply(ctx, config) {
|
|
|
919
908
|
authority: 2
|
|
920
909
|
}).action(async ({ session }, moduleTitle) => {
|
|
921
910
|
await session.send(`✅ 同步中,请前往控制台查看:${config.logsUrl}`);
|
|
922
|
-
await syncSingleModule(
|
|
911
|
+
await syncSingleModule(
|
|
912
|
+
ctx.wikibot.wikigg,
|
|
913
|
+
ctx.wikibot.bwiki,
|
|
914
|
+
moduleTitle,
|
|
915
|
+
"sync-bot"
|
|
916
|
+
).then(() => {
|
|
923
917
|
session.send(
|
|
924
918
|
`✅ 已尝试同步模块:${moduleTitle},请前往控制台查看:${config.logsUrl}`
|
|
925
919
|
);
|
|
@@ -932,7 +926,7 @@ function apply(ctx, config) {
|
|
|
932
926
|
await session.send(
|
|
933
927
|
`🚀 开始同步所有模块,任务耗时较长,请前往控制台查看:${config.logsUrl}`
|
|
934
928
|
);
|
|
935
|
-
await syncModules(
|
|
929
|
+
await syncModules(ctx.wikibot.wikigg, ctx.wikibot.bwiki).then(() => {
|
|
936
930
|
session.send(
|
|
937
931
|
`✅ 已尝试同步所有模块,请前往控制台查看:${config.logsUrl}`
|
|
938
932
|
);
|
|
@@ -948,10 +942,9 @@ function apply(ctx, config) {
|
|
|
948
942
|
`🚀 开始同步,任务可能耗时较长,请前往控制台查看:${config.logsUrl}`
|
|
949
943
|
);
|
|
950
944
|
await syncSingleImage(
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
`${imgTitle.startsWith("File:") ? "" : "File:"}${imgTitle}
|
|
954
|
-
config
|
|
945
|
+
ctx.wikibot.wikigg,
|
|
946
|
+
ctx.wikibot.bwiki,
|
|
947
|
+
`${imgTitle.startsWith("File:") ? "" : "File:"}${imgTitle}`
|
|
955
948
|
).then(() => {
|
|
956
949
|
session.send(`✅ 已尝试同步图片:${imgTitle}`);
|
|
957
950
|
}).catch((err) => {
|
|
@@ -963,7 +956,7 @@ function apply(ctx, config) {
|
|
|
963
956
|
session.send(
|
|
964
957
|
`🚀 开始同步所有图片,任务耗时较长,请前往控制台查看:${config.logsUrl}`
|
|
965
958
|
);
|
|
966
|
-
await syncAllImages(
|
|
959
|
+
await syncAllImages(ctx.wikibot.wikigg, ctx.wikibot.bwiki).then(() => {
|
|
967
960
|
session.send(
|
|
968
961
|
`✅ 已尝试同步所有图片,请前往控制台查看:${config.logsUrl}`
|
|
969
962
|
);
|
|
@@ -974,6 +967,39 @@ function apply(ctx, config) {
|
|
|
974
967
|
log.error(`同步所有图片失败,错误信息:${err}`);
|
|
975
968
|
});
|
|
976
969
|
});
|
|
970
|
+
ctx.command("sync <pageTitle:string>", "同步指定页面", { authority: 2 }).action(async ({ session }, pageTitle) => {
|
|
971
|
+
await syncSinglePage(
|
|
972
|
+
ctx.wikibot.wikigg,
|
|
973
|
+
ctx.wikibot.bwiki,
|
|
974
|
+
pageTitle,
|
|
975
|
+
"sync-bot"
|
|
976
|
+
).then(() => {
|
|
977
|
+
session.send(
|
|
978
|
+
`✅ 已尝试同步页面:${pageTitle},请前往控制台查看:${config.logsUrl}`
|
|
979
|
+
);
|
|
980
|
+
}).catch((err) => {
|
|
981
|
+
session.send(`❌ 同步页面失败:${pageTitle}`);
|
|
982
|
+
log.error(`,错误信息:${err}`);
|
|
983
|
+
});
|
|
984
|
+
});
|
|
985
|
+
}
|
|
986
|
+
__name(apply4, "apply");
|
|
987
|
+
|
|
988
|
+
// src/wiki/querywiki.ts
|
|
989
|
+
var import_koishi9 = require("koishi");
|
|
990
|
+
var Config5 = import_koishi9.Schema.object({
|
|
991
|
+
domain: import_koishi9.Schema.string().description("你的短链域名(必填,如:klei.vip)").default("klei.vip")
|
|
992
|
+
});
|
|
993
|
+
function queryWiki(ctx, config) {
|
|
994
|
+
const log = ctx.logger("querywiki");
|
|
995
|
+
ctx.model.extend("wikipages", {
|
|
996
|
+
id: "integer",
|
|
997
|
+
title: "string",
|
|
998
|
+
pinyin_full: "string",
|
|
999
|
+
// 全拼
|
|
1000
|
+
pinyin_first: "string"
|
|
1001
|
+
// 首字母
|
|
1002
|
+
});
|
|
977
1003
|
ctx.command("x <itemName>", "查询缺氧中文wiki,精准匹配+拼音模糊匹配").alias("/查wiki").action(async ({ session }, itemName = "") => {
|
|
978
1004
|
const queryKey = itemName.trim().toLowerCase();
|
|
979
1005
|
if (queryKey === "")
|
|
@@ -1073,7 +1099,7 @@ bwiki: https://${config.domain}/bw/${id}`;
|
|
|
1073
1099
|
ctx.command("update", "更新本地页面缓存(主站)", { authority: 2 }).action(async ({ session }) => {
|
|
1074
1100
|
await session.execute("update.status");
|
|
1075
1101
|
try {
|
|
1076
|
-
const res = await
|
|
1102
|
+
const res = await ctx.wikibot.wikigg.request({
|
|
1077
1103
|
action: "query",
|
|
1078
1104
|
list: "allpages",
|
|
1079
1105
|
format: "json",
|
|
@@ -1127,7 +1153,7 @@ bwiki: https://${config.domain}/bw/${id}`;
|
|
|
1127
1153
|
return "❌ 参数错误!用法:redirect <原页面名> <目标页面名>";
|
|
1128
1154
|
}
|
|
1129
1155
|
try {
|
|
1130
|
-
await
|
|
1156
|
+
await ctx.wikibot.wikigg.create(
|
|
1131
1157
|
pageName,
|
|
1132
1158
|
`#REDIRECT [[${targetPageName}]]`,
|
|
1133
1159
|
"来自qq机器人的添加重定向页面请求"
|
|
@@ -1141,7 +1167,27 @@ bwiki: https://${config.domain}/bw/${id}`;
|
|
|
1141
1167
|
}
|
|
1142
1168
|
});
|
|
1143
1169
|
}
|
|
1144
|
-
__name(
|
|
1170
|
+
__name(queryWiki, "queryWiki");
|
|
1171
|
+
|
|
1172
|
+
// src/index.ts
|
|
1173
|
+
var name = "oni-sync-bot";
|
|
1174
|
+
var inject = ["console", "database", "server", "cron"];
|
|
1175
|
+
var Config6 = import_koishi10.Schema.object({});
|
|
1176
|
+
function apply5(ctx, config) {
|
|
1177
|
+
const log = ctx.logger("oni-sync");
|
|
1178
|
+
ctx.inject(["console"], (ctx2) => {
|
|
1179
|
+
ctx2.console.addEntry({
|
|
1180
|
+
dev: (0, import_path.resolve)(__dirname, "../client/index.ts"),
|
|
1181
|
+
prod: (0, import_path.resolve)(__dirname, "../dist")
|
|
1182
|
+
});
|
|
1183
|
+
});
|
|
1184
|
+
ctx.plugin(apply, config);
|
|
1185
|
+
ctx.plugin(apply2, config);
|
|
1186
|
+
ctx.plugin(apply3, config);
|
|
1187
|
+
ctx.plugin(apply4, config);
|
|
1188
|
+
ctx.plugin(queryWiki, config);
|
|
1189
|
+
}
|
|
1190
|
+
__name(apply5, "apply");
|
|
1145
1191
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1146
1192
|
0 && (module.exports = {
|
|
1147
1193
|
Config,
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Logger, Context, Schema } from "koishi";
|
|
2
|
+
export declare const name = "logspush";
|
|
3
|
+
export declare const usage = "\u65E5\u5FD7\u63A8\u9001";
|
|
4
|
+
export interface Config {
|
|
5
|
+
logsUrl: string;
|
|
6
|
+
}
|
|
7
|
+
export declare const Config: Schema<Config>;
|
|
8
|
+
declare module "@koishijs/console" {
|
|
9
|
+
namespace Console {
|
|
10
|
+
interface Services {
|
|
11
|
+
onilogs: DataService<Logger.Record[]>;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
export declare let logBuffer: Logger.Record[];
|
|
16
|
+
export default function apply(ctx: Context, config: Config): void;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Context, Schema } from "koishi";
|
|
2
|
+
export interface Config {
|
|
3
|
+
main_site: string;
|
|
4
|
+
bwiki_site: string;
|
|
5
|
+
}
|
|
6
|
+
export declare const Config: Schema<Config>;
|
|
7
|
+
export declare const name = "wikirouter";
|
|
8
|
+
export declare const usage = "wiki\u8DEF\u7531\u91CD\u5B9A\u5411";
|
|
9
|
+
export default function apply(ctx: Context, config: Config): void;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { Mwn } from "mwn";
|
|
2
|
+
export declare const CONFIG: {
|
|
3
|
+
IGNORED_IMAGES: any[];
|
|
4
|
+
SYNC_INTERVAL_SUCCESS: number;
|
|
5
|
+
SYNC_INTERVAL_FAILED: number;
|
|
6
|
+
UPLOAD_COMMENT: string;
|
|
7
|
+
UPLOAD_TEXT: string;
|
|
8
|
+
};
|
|
9
|
+
interface ImageInfo {
|
|
10
|
+
url: string;
|
|
11
|
+
sha1: string;
|
|
12
|
+
size?: number;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* 获取图片的原始URL和SHA1
|
|
16
|
+
*/
|
|
17
|
+
declare function getImageInfo(site: Mwn, fileName: string): Promise<ImageInfo | null>;
|
|
18
|
+
/**
|
|
19
|
+
* 同步单个图片
|
|
20
|
+
*/
|
|
21
|
+
declare function syncSingleImage(sourceBot: Mwn, targetBot: Mwn, fileName: string): Promise<{
|
|
22
|
+
success: boolean;
|
|
23
|
+
reason?: string;
|
|
24
|
+
}>;
|
|
25
|
+
/**
|
|
26
|
+
* 批量同步所有图片(带失败重试)
|
|
27
|
+
*/
|
|
28
|
+
declare function syncAllImages(sourceBot: Mwn, targetBot: Mwn): Promise<void>;
|
|
29
|
+
export { syncSingleImage, syncAllImages, getImageInfo };
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { Mwn } from "mwn";
|
|
2
|
+
/**
|
|
3
|
+
* 单页面同步
|
|
4
|
+
* @param oldSite 源站点机器人实例
|
|
5
|
+
* @param newSite 目标站点机器人实例
|
|
6
|
+
* @param pageTitle 同步的标题
|
|
7
|
+
* @param user 触发更改的用户
|
|
8
|
+
* @returns success: boolean;reason: string;
|
|
9
|
+
}
|
|
10
|
+
*/
|
|
11
|
+
declare function syncSinglePage(oldSite: Mwn, newSite: Mwn, pageTitle: string, user: string): Promise<{
|
|
12
|
+
success: boolean;
|
|
13
|
+
reason: string;
|
|
14
|
+
}>;
|
|
15
|
+
/**
|
|
16
|
+
* 同步所有页面
|
|
17
|
+
* @param oldSite 源站点机器人实例
|
|
18
|
+
* @param newSite 目标站点机器人实例
|
|
19
|
+
* @returns null
|
|
20
|
+
*/
|
|
21
|
+
declare function syncPages(oldSite: Mwn, newSite: Mwn): Promise<void>;
|
|
22
|
+
/**
|
|
23
|
+
* 增量更新
|
|
24
|
+
* @param oldSite 源站点机器人实例
|
|
25
|
+
* @param newSite 目标站点机器人实例
|
|
26
|
+
* @param config KOISHI用户配置的项
|
|
27
|
+
*/
|
|
28
|
+
declare function incrementalUpdate(oldSite: Mwn, newSite: Mwn): Promise<void>;
|
|
29
|
+
export { syncSinglePage, syncPages, incrementalUpdate };
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { Context, Schema } from "koishi";
|
|
2
|
+
export declare const name = "synctask";
|
|
3
|
+
export declare const usage = "\u5B9A\u65F6\u540C\u6B65\u4EFB\u52A1";
|
|
4
|
+
export interface Config {
|
|
5
|
+
logsUrl: string;
|
|
6
|
+
}
|
|
7
|
+
export declare const Config: Schema<Config>;
|
|
8
|
+
export default function apply(ctx: Context, config: Config): void;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { Context, Schema } from "koishi";
|
|
2
|
+
export declare const name = "querywiki";
|
|
3
|
+
export declare const usage = "\u67E5\u8BE2Wiki";
|
|
4
|
+
export interface Config {
|
|
5
|
+
domain: string;
|
|
6
|
+
}
|
|
7
|
+
export declare const Config: Schema<Config>;
|
|
8
|
+
declare module "koishi" {
|
|
9
|
+
interface Tables {
|
|
10
|
+
wikipages: WikiPages;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
export interface WikiPages {
|
|
14
|
+
id: number;
|
|
15
|
+
title: string;
|
|
16
|
+
pinyin_full: string;
|
|
17
|
+
pinyin_first: string;
|
|
18
|
+
}
|
|
19
|
+
export default function queryWiki(ctx: Context, config: Config): void;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { Context, Schema } from "koishi";
|
|
2
|
+
import { Mwn } from "mwn";
|
|
3
|
+
export declare const name = "wikicore";
|
|
4
|
+
export declare const usage = "wikicore";
|
|
5
|
+
declare module "koishi" {
|
|
6
|
+
interface Context {
|
|
7
|
+
wikibot: {
|
|
8
|
+
wikigg: Mwn;
|
|
9
|
+
bwiki: Mwn;
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
export interface Config {
|
|
14
|
+
ggUsername: string;
|
|
15
|
+
ggPassword: string;
|
|
16
|
+
bwikiusername: string;
|
|
17
|
+
bwikipassword: string;
|
|
18
|
+
domain: string;
|
|
19
|
+
logsUrl: string;
|
|
20
|
+
}
|
|
21
|
+
export declare const Config: Schema<Config>;
|
|
22
|
+
export default function apply(ctx: Context, config: Config): void;
|
|
23
|
+
/**
|
|
24
|
+
* 登录机器人
|
|
25
|
+
* @param siteConfig 站点配置
|
|
26
|
+
* @returns 机器人实例
|
|
27
|
+
*/
|
|
28
|
+
export declare function login(siteConfig: ISiteConfig): Promise<Mwn>;
|
|
29
|
+
export interface ISiteConfig {
|
|
30
|
+
name: string;
|
|
31
|
+
api: string;
|
|
32
|
+
username: string;
|
|
33
|
+
password: string;
|
|
34
|
+
userAgent: string;
|
|
35
|
+
}
|
|
36
|
+
interface ISitesConfig {
|
|
37
|
+
gg: ISiteConfig;
|
|
38
|
+
bwiki: ISiteConfig;
|
|
39
|
+
}
|
|
40
|
+
export declare function getSitesConfig(config: Config): ISitesConfig;
|
|
41
|
+
export {};
|