koishi-plugin-minecraft-notifier 1.6.0 → 1.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/lib/index.cjs CHANGED
@@ -63,26 +63,94 @@ function createBotTextMsgNode(bot, content) {
63
63
  // src/translation-fetcher.ts
64
64
  var import_axios = __toESM(require("axios"), 1);
65
65
  var cheerio = __toESM(require("cheerio"), 1);
66
- async function extractTranslations(ctx, searchStr) {
66
+ async function fetchGitCodeTranslations(ctx, owner, repo, path3, token, branch = "master") {
67
+ try {
68
+ const url = `https://api.gitcode.com/api/v5/repos/${owner}/${repo}/contents/${path3}`;
69
+ const response = await import_axios.default.get(url, {
70
+ params: { ref: branch, access_token: token },
71
+ headers: { Authorization: `Bearer ${token}` }
72
+ });
73
+ if (!response.data?.content) {
74
+ ctx.logger("translation-extractor").warn(
75
+ "GitCode file has no content"
76
+ );
77
+ return [];
78
+ }
79
+ const content = Buffer.from(response.data.content, "base64").toString(
80
+ "utf-8"
81
+ );
82
+ return parseTranslationContent(content);
83
+ } catch (error) {
84
+ ctx.logger("translation-extractor").warn(
85
+ "Failed to fetch GitCode translations:",
86
+ error.response?.data || error.message
87
+ );
88
+ return [];
89
+ }
90
+ }
91
+ function parseTranslationContent(content) {
92
+ const translations = [];
93
+ try {
94
+ const parsed = JSON.parse(content);
95
+ if (Array.isArray(parsed)) {
96
+ for (const item of parsed) {
97
+ if (item.english && item.chinese) {
98
+ translations.push({
99
+ english: item.english.trim(),
100
+ chinese: item.chinese.trim()
101
+ });
102
+ }
103
+ }
104
+ } else if (typeof parsed === "object") {
105
+ for (const [english, chinese] of Object.entries(parsed)) {
106
+ if (typeof chinese === "string") {
107
+ translations.push({
108
+ english: english.trim(),
109
+ chinese: chinese.trim()
110
+ });
111
+ }
112
+ }
113
+ }
114
+ return translations;
115
+ } catch {
116
+ const lines = content.split("\n");
117
+ for (const line of lines) {
118
+ const trimmed = line.trim();
119
+ if (!trimmed || trimmed.startsWith("#") || trimmed.startsWith("//")) {
120
+ continue;
121
+ }
122
+ if (trimmed.includes(":")) {
123
+ const [english, chinese] = trimmed.split(":").map((s) => s.trim());
124
+ if (english && chinese) {
125
+ translations.push({ english, chinese });
126
+ }
127
+ } else if (trimmed.includes(",")) {
128
+ const [english, chinese] = trimmed.split(",").map((s) => s.trim());
129
+ if (english && chinese) {
130
+ translations.push({ english, chinese });
131
+ }
132
+ }
133
+ }
134
+ return translations;
135
+ }
136
+ }
137
+ async function fetchWikiTranslations(ctx) {
67
138
  try {
68
139
  const response = await import_axios.default.get(
69
140
  "https://zh.minecraft.wiki/w/Minecraft_Wiki:%E8%AF%91%E5%90%8D%E6%A0%87%E5%87%86%E5%8C%96"
70
141
  );
71
142
  const html = response.data;
72
143
  const $ = cheerio.load(html);
73
- const matches = [];
144
+ const translations = [];
74
145
  $(".data-table").each((index, table) => {
75
146
  const rows = $(table).find("tr");
76
- let headers = null;
77
147
  let englishCol = -1;
78
148
  let chineseCol = -1;
79
149
  rows.each((rowIndex, row) => {
80
150
  const cells = $(row).find("td, th");
81
151
  if (rowIndex === 0) {
82
- headers = [];
83
152
  cells.each((colIndex, cell) => {
84
153
  const headerText = $(cell).text().trim();
85
- headers.push(headerText);
86
154
  if (headerText.includes("\u82F1\u6587") || headerText.includes("English")) {
87
155
  englishCol = colIndex;
88
156
  }
@@ -96,26 +164,62 @@ async function extractTranslations(ctx, searchStr) {
96
164
  const english = $(cells[englishCol]).text().trim();
97
165
  const chinese = $(cells[chineseCol]).text().trim();
98
166
  if (english && chinese) {
99
- if (searchStr.includes(english.toLowerCase())) {
100
- matches.push({ english, chinese });
101
- }
167
+ translations.push({ english, chinese });
102
168
  }
103
169
  }
104
170
  });
105
171
  });
172
+ return translations;
173
+ } catch (error) {
174
+ ctx.logger("translation-extractor").warn(
175
+ "Failed to fetch Wiki translations:",
176
+ error
177
+ );
178
+ return [];
179
+ }
180
+ }
181
+ async function extractTranslations(ctx, cfg, searchStr) {
182
+ try {
183
+ const [wikiTranslations, gitcodeTranslations] = await Promise.all([
184
+ fetchWikiTranslations(ctx),
185
+ cfg.gitcodeApiToken && cfg.gitcodeOwner && cfg.gitcodeRepo ? fetchGitCodeTranslations(
186
+ ctx,
187
+ cfg.gitcodeOwner,
188
+ cfg.gitcodeRepo,
189
+ "Translations.json",
190
+ cfg.gitcodeApiToken
191
+ ) : Promise.resolve([])
192
+ ]);
193
+ const translationMap = /* @__PURE__ */ new Map();
194
+ for (const { english, chinese } of gitcodeTranslations) {
195
+ translationMap.set(english.toLowerCase(), chinese);
196
+ }
197
+ for (const { english, chinese } of wikiTranslations) {
198
+ translationMap.set(english.toLowerCase(), chinese);
199
+ }
200
+ const lowerSearchStr = searchStr.toLowerCase();
201
+ const matches = [];
202
+ for (const [englishLower, chinese] of translationMap.entries()) {
203
+ if (lowerSearchStr.includes(englishLower)) {
204
+ const originalEnglish = [...wikiTranslations, ...gitcodeTranslations].find(
205
+ (t) => t.english.toLowerCase() === englishLower
206
+ )?.english || englishLower;
207
+ matches.push({ english: originalEnglish, chinese });
208
+ }
209
+ }
106
210
  return matches.map(({ english, chinese }) => `${english}: ${chinese}`).join("\n");
107
211
  } catch (error) {
108
- ctx.logger("minecraft-notifier").warn(
109
- "Failed to fetch or parse translations:",
212
+ ctx.logger("translation-extractor").warn(
213
+ "Failed to extract translations:",
110
214
  error
111
215
  );
112
- return;
216
+ return "";
113
217
  }
114
218
  }
115
219
 
116
220
  // src/prompt-const.ts
117
- async function getSustemPrompt(ctx, searchStr) {
118
- const translations = await extractTranslations(ctx, searchStr);
221
+ async function getSustemPrompt(ctx, cfg, searchStr) {
222
+ const translations = await extractTranslations(ctx, cfg, searchStr);
119
223
  return `
120
224
  # Role: Minecraft Update Log JSON Summarization Specialist
121
225
 
@@ -137,7 +241,7 @@ async function getSustemPrompt(ctx, searchStr) {
137
241
 
138
242
  2. Localization and Format Governance
139
243
  - Chinese Composition: Use fluent Chinese throughout, retaining necessary English proper nouns.
140
- - Terminology Standards: Use community/official translations; retain English terms for internal mechanisms to prevent mistranslation (e.g., Charge).
244
+ - Terminology Standards: Use community/official translations; retain English terms for internal mechanisms to prevent mistranslation.
141
245
  - Emoji Selection: Choose intuitive, non-duplicated emojis for subcategories to enhance recognition and readability.
142
246
 
143
247
  ## Rules
@@ -146,7 +250,8 @@ async function getSustemPrompt(ctx, searchStr) {
146
250
  - Chinese Output: Use fluent Chinese for all entries unless the English term is untranslatable proprietary nomenclature.
147
251
  - Concise Sentences: Keep each entry under \u201Cgeneral\u201D and \u201Citems\u201D within 50-100 characters, ensuring complete and readable meaning.
148
252
  - Accurate Categorization: Strictly map to five major categories, avoiding cross-classification or overly broad descriptions.
149
- - Terminology Standards: Use standardized translations below whenever possible; e.g., ${translations}
253
+ - Terminology Standards: Use standardized translations below whenever possible; e.g.,
254
+ ${translations}
150
255
 
151
256
  2. Behavioral Guidelines:
152
257
  - Merge Similar Updates: Consolidate duplicate or highly similar updates into a single entry, highlighting core changes.
@@ -165,7 +270,7 @@ async function getSustemPrompt(ctx, searchStr) {
165
270
  - Step 1: Parse the original text, extract all changes, and preliminarily label them as new additions, optimizations, balancing, fixes, or technical changes.
166
271
  - Step 2: Create subcategories (2-6 per category) based on thematic clustering and scope of impact; assign unique emojis to each subcategory.
167
272
  - Step 3: Assign remaining scattered entries to general; merge and deduplicate redundant or similar content.
168
- - Step 4: Perform Chinese localization and terminology proofreading; retain necessary English proper nouns. Example: Lunge \u2192 \u7A81\u8FDB; Retain Charge.
273
+ - Step 4: Perform Chinese localization and terminology proofreading; retain necessary English proper nouns. Example: Lunge \u2192 \u7A81\u8FDB;
169
274
  - Step 5: Build JSON, validating structure keys, subcategory names, Emoji uniqueness, entry length, and deduplication.
170
275
  - Expected result: Produce structured JSON containing only five major categories, with concise Chinese entries, logical grouping, standardized spacing, unique Emojis, and readiness for group chats and publishing.
171
276
 
@@ -206,7 +311,7 @@ async function getSustemPrompt(ctx, searchStr) {
206
311
 
207
312
  2. Localization and Format Governance
208
313
  - Chinese Composition: Use fluent Chinese throughout, retaining necessary English proper nouns.
209
- - Terminology Standards: Use community/official translations; retain English terms for internal mechanisms to prevent mistranslation (e.g., Charge).
314
+ - Terminology Standards: Use community/official translations; retain English terms for internal mechanisms to prevent mistranslation.
210
315
  - Emoji Selection: Choose intuitive, non-duplicated emojis for subcategories to enhance recognition and readability.
211
316
 
212
317
  ## Rules
@@ -234,7 +339,7 @@ async function getSustemPrompt(ctx, searchStr) {
234
339
  - Step 1: Parse the original text, extract all changes, and preliminarily label them as new additions, optimizations, balancing, fixes, or technical changes.
235
340
  - Step 2: Create subcategories (2-6 per category) based on thematic clustering and scope of impact; assign unique emojis to each subcategory.
236
341
  - Step 3: Assign remaining scattered entries to general; merge and deduplicate redundant or similar content.
237
- - Step 4: Perform Chinese localization and terminology proofreading; retain necessary English proper nouns. Example: Lunge \u2192 \u7A81\u8FDB; Retain Charge.
342
+ - Step 4: Perform Chinese localization and terminology proofreading; retain necessary English proper nouns. Example: Lunge \u2192 \u7A81\u8FDB;.
238
343
  - Step 5: Build JSON, validating structure keys, subcategory names, Emoji uniqueness, entry length, and deduplication.
239
344
  - Expected result: Produce structured JSON containing only five major categories, with concise Chinese entries, logical grouping, standardized spacing, unique Emojis, and readiness for group chats and publishing.
240
345
 
@@ -722,6 +827,7 @@ ${updateContent}
722
827
  role: "system",
723
828
  content: await getSustemPrompt(
724
829
  ctx,
830
+ cfg,
725
831
  updateContent.toLowerCase()
726
832
  )
727
833
  },
@@ -1039,16 +1145,7 @@ function apply(ctx, cfg) {
1039
1145
  );
1040
1146
  ctx.command("mc.trigger.gitcode", "\u624B\u52A8\u89E6\u53D1 AI \u66F4\u65B0\u65E5\u5FD7\u603B\u7ED3\u751F\u6210").action(
1041
1147
  async () => {
1042
- await upsertFileToGitCode(
1043
- ctx,
1044
- cfg.gitcodeOwner,
1045
- cfg.gitcodeRepo,
1046
- "Custom.xaml.ini",
1047
- "25w43a",
1048
- `feat: update PCL HomePage XAML INI for version 25w43a`,
1049
- cfg.gitcodeApiToken,
1050
- "master"
1051
- );
1148
+ return await getSustemPrompt(ctx, cfg, "jab attack");
1052
1149
  }
1053
1150
  );
1054
1151
  ctx.setInterval(async () => {
@@ -1,2 +1,3 @@
1
1
  import { Context } from 'koishi';
2
- export declare function getSustemPrompt(ctx: Context, searchStr: string): Promise<string>;
2
+ import { Config } from './index';
3
+ export declare function getSustemPrompt(ctx: Context, cfg: Config, searchStr: string): Promise<string>;
@@ -1,2 +1,10 @@
1
1
  import { Context } from 'koishi';
2
- export declare function extractTranslations(ctx: Context, searchStr: string): Promise<string>;
2
+ import { Config } from './index';
3
+ /**
4
+ * 提取所有翻译(从 Wiki 和 GitCode)
5
+ * @param ctx - Koishi 上下文
6
+ * @param cfg - 配置选项
7
+ * @param searchStr - 搜索字符串
8
+ * @returns Promise<string> 格式化的翻译结果
9
+ */
10
+ export declare function extractTranslations(ctx: Context, cfg: Config, searchStr: string): Promise<string>;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "koishi-plugin-minecraft-notifier",
3
3
  "description": "A Minecraft new version notification plugin, also featuring a PCL homepage.",
4
- "version": "1.6.0",
4
+ "version": "1.7.0",
5
5
  "main": "lib/index.cjs",
6
6
  "typings": "lib/index.d.ts",
7
7
  "type": "module",