koishi-plugin-oni-sync-bot 0.3.3 → 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 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: () => Config,
34
- apply: () => 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 import_koishi5 = require("koishi");
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/utils/login.ts
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/utils/login.ts
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,
@@ -102,18 +123,21 @@ async function login(siteConfig) {
102
123
  }
103
124
  });
104
125
  if (siteConfig.name === "bwiki") {
105
- const cookieString = "SESSDATA=666; Domain=wiki.biligame.com; Path=/oni; HttpOnly; Secure";
126
+ const cookieString = "SESSDATA=666; Domain=wiki.biligame.com; Path=/oni; HttpOnly; Secure;";
106
127
  bot.cookieJar.setCookie(cookieString, bot.options.apiUrl, (err) => {
107
128
  if (err) console.error("Cookie 注入失败:", err);
108
129
  });
130
+ bot.setRequestOptions({
131
+ headers: {
132
+ referer: "https://wiki.biligame.com/oni/"
133
+ }
134
+ });
109
135
  }
110
136
  await bot.login();
111
137
  logger.info(`✅ 成功登录 ${siteConfig.name}`);
112
138
  return bot;
113
139
  }
114
140
  __name(login, "login");
115
-
116
- // src/config/index.ts
117
141
  var userAgent = `OniSyncBot/1.0 (https://klei.vip; Charles@klei.vip)`;
118
142
  function getSitesConfig(config) {
119
143
  return {
@@ -135,11 +159,85 @@ function getSitesConfig(config) {
135
159
  }
136
160
  __name(getSitesConfig, "getSitesConfig");
137
161
 
138
- // src/sync/pageSync.ts
162
+ // src/service/logspush.ts
163
+ var import_plugin_console = require("@koishijs/plugin-console");
139
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");
140
238
 
141
239
  // src/sync/imgSync.ts
142
- var import_koishi2 = require("koishi");
240
+ var import_koishi5 = require("koishi");
143
241
  var import_node_fetch = __toESM(require("node-fetch"));
144
242
  var import_form_data = __toESM(require("form-data"));
145
243
  var CONFIG = {
@@ -174,7 +272,7 @@ async function getImageInfo(site, fileName) {
174
272
  }
175
273
  }
176
274
  __name(getImageInfo, "getImageInfo");
177
- async function syncSingleImage(sourceBot, targetBot, fileName, config) {
275
+ async function syncSingleImage(sourceBot, targetBot, fileName) {
178
276
  if (CONFIG.IGNORED_IMAGES.includes(fileName)) {
179
277
  logger.info(`[SyncImg] 🚫 图片 ${fileName} 在忽略列表,跳过`);
180
278
  return { success: true, reason: "ignored" };
@@ -187,6 +285,8 @@ async function syncSingleImage(sourceBot, targetBot, fileName, config) {
187
285
  return { success: false, reason: "source_missing" };
188
286
  }
189
287
  const targetImageInfo = await getImageInfo(targetBot, fileName);
288
+ logger.info(`原图片sha1: ${sourceImageInfo.sha1}`);
289
+ logger.info(`目标图片sha1: ${targetImageInfo.sha1}`);
190
290
  if (targetImageInfo && targetImageInfo.sha1 === sourceImageInfo.sha1) {
191
291
  logger.info(`[SyncImg] 🟡 图片 ${fileName} 已存在且内容一致,跳过`);
192
292
  return { success: true, reason: "no_change" };
@@ -236,6 +336,10 @@ async function syncSingleImage(sourceBot, targetBot, fileName, config) {
236
336
  throw new Error(`未知响应: ${JSON.stringify(responseData)}`);
237
337
  }
238
338
  } catch (error) {
339
+ if (error instanceof Error && error.message.includes("fileexists-no-change")) {
340
+ logger.info(`[SyncImg] 🟡 图片 ${fileName} 已存在且内容相同,跳过`);
341
+ return { success: true, reason: "no_change" };
342
+ }
239
343
  const errMsg = error.message || String(error);
240
344
  logger.error(`[SyncImg] ❌ 图片 ${fileName} 同步失败:`, errMsg);
241
345
  return { success: false, reason: errMsg };
@@ -262,7 +366,7 @@ async function getAllImages(site) {
262
366
  return allImages;
263
367
  }
264
368
  __name(getAllImages, "getAllImages");
265
- async function syncAllImages(sourceBot, targetBot, config) {
369
+ async function syncAllImages(sourceBot, targetBot) {
266
370
  try {
267
371
  const imageList = await getAllImages(sourceBot);
268
372
  if (imageList.length === 0) {
@@ -283,22 +387,17 @@ async function syncAllImages(sourceBot, targetBot, config) {
283
387
  `
284
388
  [SyncAllImg] 📈 进度 ${i + 1}/${imageList.length} (${progress.toFixed(1)}%)`
285
389
  );
286
- const result = await syncSingleImage(
287
- sourceBot,
288
- targetBot,
289
- fileName,
290
- config
291
- );
390
+ const result = await syncSingleImage(sourceBot, targetBot, fileName);
292
391
  if (!result.success) {
293
392
  failCount++;
294
393
  failedImages.push(fileName);
295
- await (0, import_koishi2.sleep)(CONFIG.SYNC_INTERVAL_FAILED);
394
+ await (0, import_koishi5.sleep)(CONFIG.SYNC_INTERVAL_FAILED);
296
395
  } else {
297
396
  successCount++;
298
397
  if (result.reason === "ignored" || result.reason === "no_change") {
299
398
  skipCount++;
300
399
  }
301
- await (0, import_koishi2.sleep)(CONFIG.SYNC_INTERVAL_SUCCESS);
400
+ await (0, import_koishi5.sleep)(CONFIG.SYNC_INTERVAL_SUCCESS);
302
401
  }
303
402
  }
304
403
  if (failedImages.length > 0) {
@@ -310,12 +409,7 @@ async function syncAllImages(sourceBot, targetBot, config) {
310
409
  for (const fileName of failedImages) {
311
410
  logger.info(`
312
411
  [SyncAllImg] 🔁 重试: ${fileName}`);
313
- const result = await syncSingleImage(
314
- sourceBot,
315
- targetBot,
316
- fileName,
317
- config
318
- );
412
+ const result = await syncSingleImage(sourceBot, targetBot, fileName);
319
413
  if (result.success) {
320
414
  successCount++;
321
415
  failCount--;
@@ -324,7 +418,7 @@ async function syncAllImages(sourceBot, targetBot, config) {
324
418
  stillFailed.push(fileName);
325
419
  logger.info(`[SyncAllImg] ❌ 重试失败: ${fileName}`);
326
420
  }
327
- await (0, import_koishi2.sleep)(CONFIG.SYNC_INTERVAL_SUCCESS);
421
+ await (0, import_koishi5.sleep)(CONFIG.SYNC_INTERVAL_SUCCESS);
328
422
  }
329
423
  if (stillFailed.length > 0) {
330
424
  logger.info(`
@@ -411,13 +505,13 @@ async function processPageWithStats(oldSite, newSite, pageTitle, user, stats, fa
411
505
  if (!syncResult.success) {
412
506
  stats.failCount++;
413
507
  failedPages.push(pageTitle);
414
- await (0, import_koishi3.sleep)(CONFIG2.SYNC_INTERVAL_FAILED);
508
+ await (0, import_koishi6.sleep)(CONFIG2.SYNC_INTERVAL_FAILED);
415
509
  } else {
416
510
  stats.successCount++;
417
511
  if (syncResult.reason === "ignored" || syncResult.reason === "no_change") {
418
512
  stats.skipCount++;
419
513
  }
420
- await (0, import_koishi3.sleep)(CONFIG2.SYNC_INTERVAL_SUCCESS);
514
+ await (0, import_koishi6.sleep)(CONFIG2.SYNC_INTERVAL_SUCCESS);
421
515
  }
422
516
  }
423
517
  __name(processPageWithStats, "processPageWithStats");
@@ -493,11 +587,11 @@ async function syncPages(oldSite, newSite) {
493
587
  stats.skipCount++;
494
588
  }
495
589
  logger.info(`[SyncAllPages] ✅ 页面 ${pageTitle} 重试成功`);
496
- await (0, import_koishi3.sleep)(CONFIG2.SYNC_INTERVAL_SUCCESS);
590
+ await (0, import_koishi6.sleep)(CONFIG2.SYNC_INTERVAL_SUCCESS);
497
591
  } else {
498
592
  stillFailed.push(pageTitle);
499
593
  logger.info(`[SyncAllPages] ❌ 页面 ${pageTitle} 再次失败`);
500
- await (0, import_koishi3.sleep)(CONFIG2.SYNC_INTERVAL_FAILED);
594
+ await (0, import_koishi6.sleep)(CONFIG2.SYNC_INTERVAL_FAILED);
501
595
  }
502
596
  }
503
597
  }
@@ -514,7 +608,7 @@ async function syncPages(oldSite, newSite) {
514
608
  }
515
609
  }
516
610
  __name(syncPages, "syncPages");
517
- async function incrementalUpdate(oldSite, newSite, config) {
611
+ async function incrementalUpdate(oldSite, newSite) {
518
612
  try {
519
613
  const now = /* @__PURE__ */ new Date();
520
614
  const threeHoursAgo = new Date(now.getTime() - 3 * 60 * 60 * 1e3);
@@ -557,7 +651,7 @@ async function incrementalUpdate(oldSite, newSite, config) {
557
651
  logger.info(
558
652
  `[增量更新流程] 🖼️ 检查到图片: ${title},正在尝试转存`
559
653
  );
560
- await syncSingleImage(oldSite, newSite, fileName, config);
654
+ await syncSingleImage(oldSite, newSite, fileName);
561
655
  } else {
562
656
  await syncSinglePage(
563
657
  oldSite,
@@ -566,11 +660,11 @@ async function incrementalUpdate(oldSite, newSite, config) {
566
660
  CONFIG2.INCREMENTAL_USER
567
661
  );
568
662
  }
569
- await (0, import_koishi3.sleep)(CONFIG2.SYNC_INTERVAL_SUCCESS);
663
+ await (0, import_koishi6.sleep)(CONFIG2.SYNC_INTERVAL_SUCCESS);
570
664
  } catch (error) {
571
665
  const errMsg = error instanceof Error ? error.message : String(error);
572
666
  logger.error(`[增量更新流程] ❌ 处理 ${title} 时出错:`, errMsg);
573
- await (0, import_koishi3.sleep)(CONFIG2.SYNC_INTERVAL_FAILED);
667
+ await (0, import_koishi6.sleep)(CONFIG2.SYNC_INTERVAL_FAILED);
574
668
  }
575
669
  }
576
670
  }
@@ -585,7 +679,7 @@ async function incrementalUpdate(oldSite, newSite, config) {
585
679
  __name(incrementalUpdate, "incrementalUpdate");
586
680
 
587
681
  // src/sync/moduleSync.ts
588
- var import_koishi4 = require("koishi");
682
+ var import_koishi7 = require("koishi");
589
683
  var CONFIG3 = {
590
684
  MODLE_NAMESPACE: 828,
591
685
  // 模块命名空间 (注意:这里原代码拼写为 MODLE,保留原样)
@@ -689,13 +783,13 @@ async function syncModules(oldSite, newSite) {
689
783
  if (!syncResult.success) {
690
784
  failCount++;
691
785
  failedModules.push(moduleTitle);
692
- await (0, import_koishi4.sleep)(CONFIG3.SYNC_INTERVAL_FAILED);
786
+ await (0, import_koishi7.sleep)(CONFIG3.SYNC_INTERVAL_FAILED);
693
787
  } else {
694
788
  successCount++;
695
789
  if (syncResult.reason === "ignored" || syncResult.reason === "no_change") {
696
790
  skipCount++;
697
791
  }
698
- await (0, import_koishi4.sleep)(CONFIG3.SYNC_INTERVAL_SUCCESS);
792
+ await (0, import_koishi7.sleep)(CONFIG3.SYNC_INTERVAL_SUCCESS);
699
793
  }
700
794
  }
701
795
  if (failedModules.length > 0) {
@@ -720,11 +814,11 @@ async function syncModules(oldSite, newSite) {
720
814
  skipCount++;
721
815
  }
722
816
  logger.info(`[SyncAllModules] ✅ 模块 ${moduleTitle} 重试成功`);
723
- await (0, import_koishi4.sleep)(CONFIG3.SYNC_INTERVAL_SUCCESS);
817
+ await (0, import_koishi7.sleep)(CONFIG3.SYNC_INTERVAL_SUCCESS);
724
818
  } else {
725
819
  stillFailed.push(moduleTitle);
726
820
  logger.info(`[SyncAllModules] ❌ 模块 ${moduleTitle} 再次失败`);
727
- await (0, import_koishi4.sleep)(CONFIG3.SYNC_INTERVAL_FAILED);
821
+ await (0, import_koishi7.sleep)(CONFIG3.SYNC_INTERVAL_FAILED);
728
822
  }
729
823
  }
730
824
  logger.info(`
@@ -750,135 +844,41 @@ async function syncModules(oldSite, newSite) {
750
844
  }
751
845
  __name(syncModules, "syncModules");
752
846
 
753
- // src/index.ts
754
- var name = "oni-sync-bot";
755
- var inject = ["console", "database", "server", "cron"];
756
- var logBuffer = [];
757
- var Config = import_koishi5.Schema.object({
758
- ggUsername: import_koishi5.Schema.string().description("WIKIGG 用户名").default("1"),
759
- ggPassword: import_koishi5.Schema.string().description("WIKIGG 密码").default("1"),
760
- bwikiusername: import_koishi5.Schema.string().description("bwiki用户名").default("1"),
761
- bwikipassword: import_koishi5.Schema.string().description("bwiki密码").default("1"),
762
- domain: import_koishi5.Schema.string().description("你的短链域名(必填,如:klei.vip)").default("klei.vip"),
763
- main_site: import_koishi5.Schema.string().description("主站域名(必填,如:oxygennotincluded.wiki.gg)").default("oxygennotincluded.wiki.gg/zh"),
764
- bwiki_site: import_koishi5.Schema.string().description("镜像站域名(必填,如:wiki.biligame.com)").default("wiki.biligame.com/oni"),
765
- 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")
766
850
  });
767
- var PublicLogProvider = class extends import_plugin_console.DataService {
768
- static {
769
- __name(this, "PublicLogProvider");
770
- }
771
- constructor(ctx) {
772
- super(ctx, "onilogs", { authority: 0 });
773
- }
774
- async get() {
775
- return logBuffer;
776
- }
777
- };
778
- function apply(ctx, config) {
779
- const log = ctx.logger("oni-sync");
780
- let ggbot;
781
- let bwikibot;
782
- ctx.inject(["console"], (ctx2) => {
783
- ctx2.console.addEntry({
784
- dev: (0, import_path.resolve)(__dirname, "../client/index.ts"),
785
- prod: (0, import_path.resolve)(__dirname, "../dist")
786
- });
787
- });
788
- ctx.plugin(PublicLogProvider);
789
- const target = {
790
- colors: 0,
791
- record: /* @__PURE__ */ __name((record) => {
792
- if (record.name !== "oni-sync") return;
793
- logBuffer.push(record);
794
- if (logBuffer.length > 100) {
795
- logBuffer = logBuffer.slice(-100);
796
- }
797
- ctx.get("console")?.patch("onilogs", logBuffer);
798
- }, "record")
799
- };
800
- import_koishi5.Logger.targets.push(target);
801
- ctx.on("dispose", () => {
802
- const index = import_koishi5.Logger.targets.indexOf(target);
803
- if (index > -1) import_koishi5.Logger.targets.splice(index, 1);
804
- });
805
- ctx.model.extend("wikipages", {
806
- id: "integer",
807
- title: "string",
808
- pinyin_full: "string",
809
- // 全拼
810
- pinyin_first: "string"
811
- // 首字母
812
- });
813
- ctx.server.get("/gg/:id", async (router) => {
814
- const pageId = Number(router.params.id);
815
- if (isNaN(pageId)) return router.body = "❌ 无效的页面ID,必须为数字!";
816
- const [page] = await ctx.database.get("wikipages", { id: pageId });
817
- if (!page)
818
- return router.body = `❌ 未找到ID为【${pageId}】的页面,请联系管理员更新缓存!`;
819
- const targetUrl = `https://${config.main_site}/${encodeURIComponent(
820
- page.title
821
- )}?variant=zh`;
822
- router.redirect(targetUrl);
823
- });
824
- ctx.server.get("/bw/: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.bwiki_site}/${encodeURIComponent(
831
- page.title
832
- )}`;
833
- router.redirect(targetUrl);
834
- });
851
+ function apply4(ctx, config) {
852
+ const log = ctx.logger("sync-task");
835
853
  ctx.on("ready", async () => {
836
- logger.info("初始化中...");
837
- const sitesConfig = getSitesConfig(config);
838
- ggbot = await login(sitesConfig.gg);
839
- bwikibot = await login(sitesConfig.bwiki);
840
- if (ggbot.login && bwikibot.login) {
841
- logger.info("登录成功,插件已准备就绪");
842
- } else {
843
- logger.error("登录失败,请检查配置");
844
- }
854
+ logger.info("定时同步任务已准备就绪");
845
855
  ctx.cron("15 * * * *", async () => {
846
- await incrementalUpdate(ggbot, bwikibot, config);
856
+ await incrementalUpdate(ctx.wikibot.wikigg, ctx.wikibot.bwiki);
847
857
  });
848
858
  ctx.cron("30 8 * * 4", async () => {
849
- await syncPages(ggbot, bwikibot).then(() => {
859
+ await syncPages(ctx.wikibot.wikigg, ctx.wikibot.bwiki).then(() => {
850
860
  logger.info("自动任务:尝试同步所有页面,从 WIKIGG 到 bwiki");
851
861
  }).catch((err) => {
852
862
  logger.error(`同步所有页面失败`);
853
- log.error(`,错误信息:${err}`);
863
+ ctx.logger.error(`,错误信息:${err}`);
854
864
  });
855
865
  });
856
866
  ctx.cron("30 8 * * 3", async () => {
857
- await syncAllImages(ggbot, bwikibot, config).then(() => {
867
+ await syncAllImages(ctx.wikibot.wikigg, ctx.wikibot.bwiki).then(() => {
858
868
  logger.info("自动任务:尝试同步所有图片,从 WIKIGG 到 bwiki");
859
869
  }).catch((err) => {
860
870
  logger.error(`同步所有图片失败`);
861
- log.error(`,错误信息:${err}`);
871
+ ctx.logger.error(`,错误信息:${err}`);
862
872
  });
863
873
  });
864
874
  });
865
- ctx.command("sync <pageTitle:string>", "同步指定页面", { authority: 2 }).action(async ({ session }, pageTitle) => {
866
- await syncSinglePage(ggbot, bwikibot, pageTitle, "sync-bot").then(() => {
867
- session.send(
868
- `✅ 已尝试同步页面:${pageTitle},请前往控制台查看:${config.logsUrl}`
869
- );
870
- }).catch((err) => {
871
- session.send(`❌ 同步页面失败:${pageTitle}`);
872
- log.error(`,错误信息:${err}`);
873
- });
874
- });
875
875
  ctx.command("sync.incrementalUpdate", "获取3h内的编辑并尝试更新", {
876
876
  authority: 2
877
877
  }).alias("增量更新").action(async ({ session }) => {
878
878
  session.send(
879
879
  `🚀 获取3h内的编辑并尝试更新,任务耗时可能较长,请前往控制台查看日志:${config.logsUrl}`
880
880
  );
881
- await incrementalUpdate(ggbot, bwikibot, config).then(() => {
881
+ await incrementalUpdate(ctx.wikibot.wikigg, ctx.wikibot.bwiki).then(() => {
882
882
  session.send(
883
883
  `✅ 已尝试获取三小时前的编辑并同步,请前往控制台查看:${config.logsUrl}`
884
884
  );
@@ -893,7 +893,7 @@ function apply(ctx, config) {
893
893
  session.send(
894
894
  `🚀 开始同步所有页面,任务耗时较长,请前往控制台查看日志:${config.logsUrl}`
895
895
  );
896
- await syncPages(ggbot, bwikibot).then(() => {
896
+ await syncPages(ctx.wikibot.wikigg, ctx.wikibot.bwiki).then(() => {
897
897
  session.send(
898
898
  `✅ 已尝试同步所有页面,请前往控制台查看:${config.logsUrl}`
899
899
  );
@@ -908,7 +908,12 @@ function apply(ctx, config) {
908
908
  authority: 2
909
909
  }).action(async ({ session }, moduleTitle) => {
910
910
  await session.send(`✅ 同步中,请前往控制台查看:${config.logsUrl}`);
911
- await syncSingleModule(ggbot, bwikibot, moduleTitle, "sync-bot").then(() => {
911
+ await syncSingleModule(
912
+ ctx.wikibot.wikigg,
913
+ ctx.wikibot.bwiki,
914
+ moduleTitle,
915
+ "sync-bot"
916
+ ).then(() => {
912
917
  session.send(
913
918
  `✅ 已尝试同步模块:${moduleTitle},请前往控制台查看:${config.logsUrl}`
914
919
  );
@@ -921,7 +926,7 @@ function apply(ctx, config) {
921
926
  await session.send(
922
927
  `🚀 开始同步所有模块,任务耗时较长,请前往控制台查看:${config.logsUrl}`
923
928
  );
924
- await syncModules(ggbot, bwikibot).then(() => {
929
+ await syncModules(ctx.wikibot.wikigg, ctx.wikibot.bwiki).then(() => {
925
930
  session.send(
926
931
  `✅ 已尝试同步所有模块,请前往控制台查看:${config.logsUrl}`
927
932
  );
@@ -937,10 +942,9 @@ function apply(ctx, config) {
937
942
  `🚀 开始同步,任务可能耗时较长,请前往控制台查看:${config.logsUrl}`
938
943
  );
939
944
  await syncSingleImage(
940
- ggbot,
941
- bwikibot,
942
- `${imgTitle.startsWith("File:") ? "" : "File:"}${imgTitle}`,
943
- config
945
+ ctx.wikibot.wikigg,
946
+ ctx.wikibot.bwiki,
947
+ `${imgTitle.startsWith("File:") ? "" : "File:"}${imgTitle}`
944
948
  ).then(() => {
945
949
  session.send(`✅ 已尝试同步图片:${imgTitle}`);
946
950
  }).catch((err) => {
@@ -952,7 +956,7 @@ function apply(ctx, config) {
952
956
  session.send(
953
957
  `🚀 开始同步所有图片,任务耗时较长,请前往控制台查看:${config.logsUrl}`
954
958
  );
955
- await syncAllImages(ggbot, bwikibot, config).then(() => {
959
+ await syncAllImages(ctx.wikibot.wikigg, ctx.wikibot.bwiki).then(() => {
956
960
  session.send(
957
961
  `✅ 已尝试同步所有图片,请前往控制台查看:${config.logsUrl}`
958
962
  );
@@ -963,6 +967,39 @@ function apply(ctx, config) {
963
967
  log.error(`同步所有图片失败,错误信息:${err}`);
964
968
  });
965
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
+ });
966
1003
  ctx.command("x <itemName>", "查询缺氧中文wiki,精准匹配+拼音模糊匹配").alias("/查wiki").action(async ({ session }, itemName = "") => {
967
1004
  const queryKey = itemName.trim().toLowerCase();
968
1005
  if (queryKey === "")
@@ -1062,7 +1099,7 @@ bwiki: https://${config.domain}/bw/${id}`;
1062
1099
  ctx.command("update", "更新本地页面缓存(主站)", { authority: 2 }).action(async ({ session }) => {
1063
1100
  await session.execute("update.status");
1064
1101
  try {
1065
- const res = await ggbot.request({
1102
+ const res = await ctx.wikibot.wikigg.request({
1066
1103
  action: "query",
1067
1104
  list: "allpages",
1068
1105
  format: "json",
@@ -1116,7 +1153,7 @@ bwiki: https://${config.domain}/bw/${id}`;
1116
1153
  return "❌ 参数错误!用法:redirect <原页面名> <目标页面名>";
1117
1154
  }
1118
1155
  try {
1119
- await ggbot.create(
1156
+ await ctx.wikibot.wikigg.create(
1120
1157
  pageName,
1121
1158
  `#REDIRECT [[${targetPageName}]]`,
1122
1159
  "来自qq机器人的添加重定向页面请求"
@@ -1130,7 +1167,27 @@ bwiki: https://${config.domain}/bw/${id}`;
1130
1167
  }
1131
1168
  });
1132
1169
  }
1133
- __name(apply, "apply");
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");
1134
1191
  // Annotate the CommonJS export names for ESM import in node:
1135
1192
  0 && (module.exports = {
1136
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 {};
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "koishi-plugin-oni-sync-bot",
3
3
  "description": "缺氧Wiki站镜像点同步-测试",
4
- "version": "0.3.3",
4
+ "version": "0.4.1",
5
5
  "main": "lib/index.js",
6
6
  "typings": "lib/index.d.ts",
7
7
  "files": [