koishi-plugin-dwrgbwiki 2.1.3 → 2.2.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.
Files changed (4) hide show
  1. package/index.js +87 -58
  2. package/notice.js +4 -1
  3. package/package.json +1 -1
  4. package/readme.md +6 -13
package/index.js CHANGED
@@ -117,36 +117,20 @@ module.exports = {
117
117
  width: Schema.number().min(400).max(4000)
118
118
  .description('图片宽度(px),其他指令未单独设置时使用该值')
119
119
  .default(1300),
120
- winrateWidth: Schema.number().min(0).max(4000)
121
- .description('胜率指令图片宽度(px),0=使用默认宽度')
122
- .default(0),
123
- mapWidth: Schema.number().min(0).max(4000)
124
- .description('地图指令图片宽度(px),0=使用默认宽度')
125
- .default(0),
126
- mimicWidth: Schema.number().min(0).max(4000)
127
- .description('模仿者指令图片宽度(px),0=使用默认宽度')
128
- .default(0),
129
- matchWidth: Schema.number().min(0).max(4000)
130
- .description('赛事指令图片宽度(px),0=使用默认宽度')
131
- .default(0),
120
+ commandWidths: Schema.array(Schema.object({
121
+ command: Schema.union(['胜率', '地图', '模仿者', '赛事', '勋章', '基础数据', '抽卡', '图鉴', 'WIKI'])
122
+ .required()
123
+ .description('指令名称'),
124
+ width: Schema.number().min(0).max(4000)
125
+ .description('该指令图片宽度(px),0=使用默认宽度')
126
+ .default(0),
127
+ }))
128
+ .role('table')
129
+ .description('各指令图片宽度设置(px),以表格形式通过「添加项目」新增;0=使用默认宽度')
130
+ .default([]),
132
131
  matchMerge: Schema.union(['team', 'player', 'all', 'none'])
133
132
  .description('赛事指令默认合并模式:team=合并队伍前身,player=合并选手多个id,all=两者都合并,none=完全不合并')
134
133
  .default('team'),
135
- badgeWidth: Schema.number().min(0).max(4000)
136
- .description('勋章指令图片宽度(px),0=使用默认宽度')
137
- .default(0),
138
- basicWidth: Schema.number().min(0).max(4000)
139
- .description('基础数据指令图片宽度(px),0=使用默认宽度')
140
- .default(0),
141
- gachaWidth: Schema.number().min(0).max(4000)
142
- .description('抽卡指令图片宽度(px),0=使用默认宽度')
143
- .default(0),
144
- codexWidth: Schema.number().min(0).max(4000)
145
- .description('图鉴指令图片宽度(px),0=使用默认宽度')
146
- .default(0),
147
- wikiWidth: Schema.number().min(400).max(4000)
148
- .description('WIKI页面指令截图宽度(px)')
149
- .default(1300),
150
134
  wikiMaxHeight: Schema.number().min(200).max(12000)
151
135
  .description('WIKI页面指令截图最大高度(px)')
152
136
  .default(5000),
@@ -210,12 +194,16 @@ module.exports = {
210
194
  noticePlatform: Schema.string()
211
195
  .description('公告推送的平台(如 qq),留空禁用公告推送')
212
196
  .default('qq'),
213
- noticeChannelType: Schema.union(['channel', 'private'])
214
- .description('公告推送目标类型:channel=群/频道,private=私聊')
215
- .default('channel'),
216
- noticeChannelId: Schema.string()
217
- .description('公告推送目标:群/频道 id(channel 类型)或用户 id(private 类型)')
218
- .default(''),
197
+ noticeTargets: Schema.array(Schema.object({
198
+ type: Schema.union(['channel', 'private'])
199
+ .description('目标类型:channel=群/频道,private=私聊')
200
+ .default('channel'),
201
+ id: Schema.string().required()
202
+ .description('群/频道 id(channel 类型)或用户 id(private 类型)'),
203
+ }))
204
+ .role('table')
205
+ .description('公告推送目标列表,以表格形式通过「添加项目」新增推送目标(每行一个目标),可添加多个,群/频道与私聊可同时推送')
206
+ .default([]),
219
207
  noticeInterval: Schema.number().min(1).max(1440)
220
208
  .description('公告检查间隔(分钟)')
221
209
  .default(10),
@@ -233,10 +221,10 @@ module.exports = {
233
221
  key: Schema.string().required()
234
222
  .description('模板参数名'),
235
223
  label: Schema.string()
236
- .description('显示名,留空用参数名')
237
- .default(''),
224
+ .description('显示名,留空则显示参数名'),
238
225
  }))
239
- .description('要解析展示的参数,可增减')
226
+ .role('table')
227
+ .description('要解析展示的参数,以表格形式通过「添加项目」新增(每行一个参数);新增时默认只填 key,label 可留空或按需填写')
240
228
  .default([]),
241
229
  image: Schema.string()
242
230
  .description('配图文件名模板(用 {{参数名}} 占位,如 {{角色}}{{品质}}品质时装_{{名称}}.png),留空不显示图片')
@@ -253,17 +241,17 @@ module.exports = {
253
241
  templates: ['单时装', '商城信息'],
254
242
  image: '{{角色}}{{品质}}品质时装_{{名称}}.png',
255
243
  fields: [
256
- { key: '名称', label: '名称' },
257
- { key: '角色', label: '角色' },
258
- { key: '品质', label: '品质' },
259
- { key: '获取方式', label: '获取方式' },
260
- { key: '价格', label: '价格' },
261
- { key: '上架时间', label: '上架时间' },
262
- { key: '下架时间', label: '下架时间' },
263
- { key: '具体描述', label: '具体描述' },
264
- { key: '备注', label: '备注' },
265
- { key: '限时限定', label: '限时限定' },
266
- { key: '英文名称', label: '英文名称' },
244
+ { key: '名称' },
245
+ { key: '角色' },
246
+ { key: '品质' },
247
+ { key: '获取方式' },
248
+ { key: '价格' },
249
+ { key: '上架时间' },
250
+ { key: '下架时间' },
251
+ { key: '具体描述' },
252
+ { key: '备注' },
253
+ { key: '限时限定' },
254
+ { key: '英文名称' },
267
255
  ],
268
256
  },
269
257
  ]),
@@ -704,7 +692,25 @@ function logCmd(ctx, session, name, args, extra) {
704
692
  } catch (e) { /* 日志失败不影响主流程 */ }
705
693
  }
706
694
 
695
+ // 指令宽度表:旧配置键 -> 表格中的指令名(commandWidths)
696
+ const WIDTH_COMMANDS = {
697
+ winrateWidth: '胜率',
698
+ mapWidth: '地图',
699
+ mimicWidth: '模仿者',
700
+ matchWidth: '赛事',
701
+ badgeWidth: '勋章',
702
+ basicWidth: '基础数据',
703
+ gachaWidth: '抽卡',
704
+ codexWidth: '图鉴',
705
+ wikiWidth: 'WIKI',
706
+ }
707
+
708
+ // 读取指令图片宽度:优先 commandWidths 表格,其次回退旧版独立配置键,最后使用默认宽度
707
709
  function cmdWidth(config, key) {
710
+ const command = WIDTH_COMMANDS[key]
711
+ const list = Array.isArray(config.commandWidths) ? config.commandWidths : []
712
+ const row = command && list.find(t => t && t.command === command)
713
+ if (row && row.width > 0) return row.width
708
714
  const v = config[key]
709
715
  return (v && v > 0) ? v : (config.width || 1300)
710
716
  }
@@ -881,6 +887,7 @@ async function codexImage(ctx, config, rest) {
881
887
  ctx.logger('dwrgbwiki').warn(e)
882
888
  const msg = e && e.message ? e.message : String(e)
883
889
  if (String(msg).includes('页面不存在')) {
890
+ await new Promise(r => setTimeout(r, 2000))
884
891
  try {
885
892
  const results = await codex.searchPages(q, config)
886
893
  if (results.length) {
@@ -974,7 +981,7 @@ async function wikiPageImage(ctx, config, wikiStore, userId, name) {
974
981
  } catch (e) {
975
982
  ctx.logger('dwrgbwiki').warn('WIKI页面解析标题失败,按原样截图: ' + (e && e.message ? e.message : e))
976
983
  }
977
- const width = config.wikiWidth || 1300
984
+ const width = cmdWidth(config, 'wikiWidth')
978
985
  const maxHeight = config.wikiMaxHeight || 5000
979
986
  const image = await wiki.screenshot(ctx, target, {
980
987
  width,
@@ -1334,21 +1341,43 @@ async function fetchNotice(url, timeout) {
1334
1341
  }
1335
1342
  }
1336
1343
 
1344
+ // 汇总公告推送目标列表(noticeTargets:多目标,群/频道与私聊可混用)
1345
+ function buildNoticeTargets(config) {
1346
+ const list = Array.isArray(config.noticeTargets) ? config.noticeTargets : []
1347
+ const targets = []
1348
+ const seen = new Set()
1349
+ for (const t of list) {
1350
+ const id = String(t && t.id ? t.id : '').trim()
1351
+ if (!id) continue
1352
+ const type = t.type === 'private' ? 'private' : 'channel'
1353
+ const key = type + ':' + id
1354
+ if (seen.has(key)) continue
1355
+ seen.add(key)
1356
+ targets.push({ type, id })
1357
+ }
1358
+ return targets
1359
+ }
1360
+
1361
+ // 推送到全部目标,任一目标成功即视为成功(其余目标失败仅记录日志)
1337
1362
  async function sendNoticeMessage(ctx, config, content, logger) {
1338
- if (!config.noticePlatform || !config.noticeChannelId) return false
1363
+ const targets = buildNoticeTargets(config)
1364
+ if (!config.noticePlatform || !targets.length) return false
1339
1365
  const bot = ctx.bots && ctx.bots.find(b => b.platform === config.noticePlatform && b.status === 1)
1340
1366
  if (!bot) return false
1341
- try {
1342
- if (config.noticeChannelType === 'private') {
1343
- await bot.sendPrivateMessage(config.noticeChannelId, content)
1344
- } else {
1345
- await bot.sendMessage(config.noticeChannelId, content)
1367
+ let ok = false
1368
+ for (const t of targets) {
1369
+ try {
1370
+ if (t.type === 'private') {
1371
+ await bot.sendPrivateMessage(t.id, content)
1372
+ } else {
1373
+ await bot.sendMessage(t.id, content)
1374
+ }
1375
+ ok = true
1376
+ } catch (e) {
1377
+ logger.warn('公告推送失败(' + t.type + ':' + t.id + '): ' + (e && e.message ? e.message : e))
1346
1378
  }
1347
- return true
1348
- } catch (e) {
1349
- logger.warn('公告推送失败: ' + (e && e.message ? e.message : e))
1350
- return false
1351
1379
  }
1380
+ return ok
1352
1381
  }
1353
1382
 
1354
1383
  // 公告渲染为图片推送;失败(无 puppeteer / 渲染出错)返回 false,由调用方回退文本
package/notice.js CHANGED
@@ -216,7 +216,10 @@ function buildNoticeHtml(parsed, config, changed) {
216
216
  const width = config.width || 1300
217
217
  const sourceName = config.sourceName || '官方'
218
218
  const title = parsed.title || '更新公告'
219
- const introLines = parsed.intro.split('\n').map(l => l.trim()).filter(Boolean)
219
+ // 增量推送(changed 非空)时,引言(第 1 个板块前的“致诸位尊敬的访客”等段落)未变动则不渲染,
220
+ // 避免每次推送都把固定引言带进图里;完整渲染(changed 为空)时始终展示
221
+ const showIntro = !changed || changed.intro
222
+ const introLines = showIntro ? parsed.intro.split('\n').map(l => l.trim()).filter(Boolean) : []
220
223
  const introHtml = introLines.length
221
224
  ? '<div class="intro' + (changed ? ' update' : '') + '">' + introLines.map(l => inlineHtml(l)).join('<br>') + '</div>'
222
225
  : ''
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "koishi-plugin-dwrgbwiki",
3
- "version": "2.1.3",
3
+ "version": "2.2.0",
4
4
  "description": "第五人格BWIKI编辑组开发,所有代码由DeepSeek V4 Flash 0731编写。支持胜率/地图/模仿者/勋章/基础数据查询、图鉴查询、wiki页面截图、藏头诗、抽卡模拟、加页手记探索、赛事数据(选手/对决)、公告变动推送、反馈系统等功能。",
5
5
  "main": "index.js",
6
6
  "files": [
package/readme.md CHANGED
@@ -115,7 +115,7 @@ WIKI页面 <页面名>
115
115
  | `图鉴 时装 招风旗` | 查询时装「招风旗」并生成图片卡片 |
116
116
 
117
117
  - 数据来自第五人格 BWIKI(`wiki.biligame.com/dwrg`),通过 `query&prop=revisions` 获取页面 wikitext 后按模板解析
118
- - 二级指令、模板名(前缀匹配,可多个)、解析字段、配图文件名模板与输出宽度均可在插件配置「图鉴二级指令配置」中自定义增减
118
+ - 二级指令、模板名(前缀匹配,可多个)、解析字段、配图文件名模板与输出宽度均可在插件配置「图鉴二级指令配置」中自定义增减;字段以表格形式通过「添加项目」新增(每行一个参数),新增时默认只填 `key`,`label` 留空则显示参数名
119
119
  - 配图文件名模板用 `{{参数名}}` 占位,如 `{{角色}}{{品质}}品质时装_{{名称}}.png`,插件会按该文件名在 wiki 上查找图片并显示在卡片左侧(找不到则不显示);参数值会自动清洗 wiki 语法(`[[链接]]`、`[[File:..]]`、`<br>` 等)
120
120
  - 每个二级指令可单独设置 `width`(输出图片宽度,0=使用默认宽度),卡片为左侧图片、右侧字段表格的版式
121
121
  - **时装专属**:`图鉴 时装 <名称>` 会额外读取 `/WIKI/时装稀有度/` 的 `latest_price.csv`(最新价格),在卡片底部显示该时装的**占有率**(含数据更新日期,占有率为动态数据);当品质为「稀世」时额外显示**单金价格**与**多金价格**
@@ -270,20 +270,12 @@ WIKI页面 <页面名>
270
270
  | `showBadge` | 显示勋章分数据 | `true` |
271
271
  | `badgeDays` | 勋章日增长率天数 | `7` |
272
272
  | `width` | 图片宽度(px),其他指令未单独设置时使用该值 | `1300` |
273
- | `winrateWidth` | 胜率指令图片宽度(px),0=使用默认宽度 | `0` |
274
- | `mapWidth` | 地图指令图片宽度(px),0=使用默认宽度 | `0` |
275
- | `mimicWidth` | 模仿者指令图片宽度(px),0=使用默认宽度 | `0` |
276
- | `badgeWidth` | 勋章指令图片宽度(px),0=使用默认宽度 | `0` |
277
- | `basicWidth` | 基础数据指令图片宽度(px),0=使用默认宽度 | `0` |
278
- | `gachaWidth` | 抽卡/探索/资源指令图片宽度(px),0=使用默认宽度 | `0` |
279
- | `codexWidth` | 图鉴指令图片宽度(px),0=使用默认宽度 | `0` |
273
+ | `commandWidths` | 各指令图片宽度表(表格形式,每行:指令名 + 宽度,0=使用默认宽度),可配置胜率/地图/模仿者/赛事/勋章/基础数据/抽卡/图鉴/WIKI | 空 |
280
274
  | `codexCommands` | 图鉴二级指令配置(名称/说明/模板名/解析字段,可增减) | 预置「时装」 |
281
- | `wikiWidth` | WIKI页面指令截图宽度(px) | `1300` |
282
275
  | `wikiMaxHeight` | WIKI页面指令截图最大高度(px) | `5000` |
283
276
  | `wikiDailyLimit` | WIKI页面指令每日使用次数上限 | `5` |
284
277
  | `cangtouDefaultMode` | 藏头指令默认模式 | `谐音` |
285
278
  | `cangtouDefaultType` | 藏头指令默认物品类型 | `所有` |
286
- | `matchWidth` | 赛事指令图片宽度(px),0=使用默认宽度 | `0` |
287
279
  | `matchMerge` | 赛事指令默认合并模式(team/player/all/none) | `team` |
288
280
  | `gachaDailyLimit` | 抽卡/探索每日次数上限 | `2` |
289
281
  | `gachaDefaultJinghua` | 抽卡-精华 默认卡池编号 | 空 |
@@ -301,8 +293,7 @@ WIKI页面 <页面名>
301
293
  | `feedbackUserId` | 接收反馈的账号 id | 空 |
302
294
  | `noticeEnable` | 启用网易公告变动监听 | `false` |
303
295
  | `noticePlatform` | 公告推送的平台(如 `qq`),留空禁用公告推送 | `qq` |
304
- | `noticeChannelType` | 公告推送目标类型(channel=群/频道,private=私聊) | `channel` |
305
- | `noticeChannelId` | 公告推送目标:群/频道 id 或用户 id | 空 |
296
+ | `noticeTargets` | 公告推送目标列表,以表格形式通过「添加项目」新增(每行一个目标:类型 channel=群/频道 或 private=私聊、目标 id),可添加多个,群/频道与私聊可同时推送 | 空 |
306
297
  | `noticeInterval` | 公告检查间隔(分钟) | `10` |
307
298
 
308
299
  数据源两个镜像:`https://website.homeworkkun.top` 与 `https://web.homeworkkun.top`,可直接在配置中切换。
@@ -320,7 +311,9 @@ WIKI页面 <页面名>
320
311
  - 正式服:`https://h55.update.netease.com/h55_notice_version2.txt`
321
312
  - 共研服:`https://h55.update.netease.com/h55_notice_gongyan_version2.txt`
322
313
 
323
- 每次内容变动(以内容哈希判断)时,通过 `noticePlatform` 平台的机器人推送到 `noticeChannelId`(`noticeChannelType` 为 `channel` 时是群/频道、`private` 时是私聊)。推送内容为「公告标题」+ 正文摘要(去除 HTML 标签与颜色代码,截断 500 字)。首次启动只记录基线,不推送。
314
+ 每次内容变动(以内容哈希判断)时,通过 `noticePlatform` 平台的机器人推送到 `noticeTargets` 列表中的全部目标(每条目标可单独指定 `channel` 群/频道或 `private` 私聊,可同时推送)。推送内容为「公告标题」+ 正文摘要(去除 HTML 标签与颜色代码,截断 500 字)。首次启动只记录基线,不推送。
315
+
316
+ 变更推送优先渲染为图片(仅包含发生变化的部分):当「致诸位尊敬的访客」等引言段落没有变动时,不再将其渲染进图中,避免每次推送都带上固定引言;若引言本身有变动则会正常展示。图片渲染失败时自动回退为纯文本摘要推送。
324
317
 
325
318
  ## 图片内容
326
319