koishi-plugin-dwrgbwiki 2.4.0 → 2.4.2
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/index.js +70 -4
- package/match.js +7 -0
- package/matchdata.js +1083 -0
- package/package.json +5 -3
- package/readme.md +67 -0
- package/sqlite_reader.js +255 -0
- package/wikiwatch.js +593 -514
package/index.js
CHANGED
|
@@ -8,6 +8,7 @@ const codex = require('./codex')
|
|
|
8
8
|
const wiki = require('./wiki')
|
|
9
9
|
const cangtou = require('./cangtou')
|
|
10
10
|
const match = require('./match')
|
|
11
|
+
const matchdata = require('./matchdata')
|
|
11
12
|
const notice = require('./notice')
|
|
12
13
|
const wikiwatch = require('./wikiwatch')
|
|
13
14
|
|
|
@@ -45,6 +46,10 @@ const MAIN_HELP = [
|
|
|
45
46
|
' 查询选手历史赛事数据,例:赛事 选手 tian',
|
|
46
47
|
' 赛事 对决 <队伍1> <队伍2>',
|
|
47
48
|
' 查询两支队伍全部交锋记录,例:赛事 对决 TE GG',
|
|
49
|
+
' 赛事 数据 <类型> [赛事名]',
|
|
50
|
+
' 按赛事出排行:求生者(队伍)/ 监管者队伍 / 监管者选手 / 队伍战绩',
|
|
51
|
+
' 例:赛事 数据 求生者 / 赛事 数据 队伍 2026COA预选赛',
|
|
52
|
+
' (赛事名可省略,用配置里的默认赛事)',
|
|
48
53
|
' 抽卡 <类型> <卡池> [次数]',
|
|
49
54
|
' 各卡池抽卡模拟,例:抽卡 精华 S37E1 10',
|
|
50
55
|
' 抽卡 加页探索 [难度]',
|
|
@@ -136,6 +141,21 @@ module.exports = {
|
|
|
136
141
|
matchMerge: Schema.union(['team', 'player', 'all', 'none'])
|
|
137
142
|
.description('赛事指令默认合并模式:team=合并队伍前身,player=合并选手多个id,all=两者都合并,none=完全不合并')
|
|
138
143
|
.default('team'),
|
|
144
|
+
matchCloud: Schema.boolean()
|
|
145
|
+
.description('是否叠加云端在架的赛事(2.0 的 overlay 机制):站点还没重建 all.db 时,正在更新的赛事也能查到')
|
|
146
|
+
.default(true),
|
|
147
|
+
matchDataSource: Schema.union(['sqlite', 'json'])
|
|
148
|
+
.description('赛事数据来源:sqlite=读 2.0 的 all.db(推荐,9MB 单文件);json=旧的 data/*.json(约 35MB,sqlite 失败时会自动回落)')
|
|
149
|
+
.default('sqlite'),
|
|
150
|
+
matchDefaultTour: Schema.string()
|
|
151
|
+
.description('「赛事 数据」的默认赛事(赛段+阶段,如 2026COA预选赛;也可只写阶段如 COA预选赛)。留空则必须手动指定赛事名')
|
|
152
|
+
.default(''),
|
|
153
|
+
matchDataMinGames: Schema.number().min(1).max(500)
|
|
154
|
+
.description('「赛事 数据」的最少局数门槛:局数低于该值的选手/队伍不进榜(1=与网站「最少局数」默认一致)')
|
|
155
|
+
.default(1),
|
|
156
|
+
matchDataTopN: Schema.number().min(0).max(500)
|
|
157
|
+
.description('「赛事 数据」最多显示多少名(0=全部)。榜单长了图片会非常长,建议 20~40')
|
|
158
|
+
.default(30),
|
|
139
159
|
wikiMaxHeight: Schema.number().min(200).max(12000)
|
|
140
160
|
.description('WIKI页面指令截图最大高度(px)')
|
|
141
161
|
.default(5000),
|
|
@@ -509,12 +529,14 @@ module.exports = {
|
|
|
509
529
|
return cangtouFullImage(ctx, config, cond)
|
|
510
530
|
})
|
|
511
531
|
|
|
512
|
-
ctx.command('赛事 <子功能> [参数1] [参数2]', '查询赛事数据(选手历史 /
|
|
513
|
-
.usage('赛事 选手 <选手id> [-i 模式]\n赛事 对决 <队伍1> <队伍2> [-i 模式]\n\n示例:\n 赛事 选手 tian\n 赛事 选手 hasha -i all\n 赛事 对决 TE GG\n 赛事 对决 ZETA SunSister -i all\n\n合并模式:team=合并队伍前身 / player=合并选手多id / all=全部 / none=不合并')
|
|
532
|
+
ctx.command('赛事 <子功能> [参数1] [参数2]', '查询赛事数据(选手历史 / 队伍对决 / 赛事排行),输出图片')
|
|
533
|
+
.usage('赛事 选手 <选手id> [-i 模式]\n赛事 对决 <队伍1> <队伍2> [-i 模式]\n赛事 数据 <类型> [赛事名] [-i 模式]\n\n示例:\n 赛事 选手 tian\n 赛事 选手 hasha -i all\n 赛事 对决 TE GG\n 赛事 对决 ZETA SunSister -i all\n 赛事 数据 求生者\n 赛事 数据 监管者选手 2026COA预选赛\n\n「赛事 数据」的类型:求生者(求生者队伍)/ 监管者队伍 / 监管者选手 / 队伍(战绩总榜);\n赛事名省略时用配置里的默认赛事\n\n合并模式:team=合并队伍前身 / player=合并选手多id / all=全部 / none=不合并')
|
|
514
534
|
.example('赛事 选手 tian')
|
|
515
535
|
.example('赛事 选手 hasha -i all')
|
|
516
536
|
.example('赛事 对决 TE GG')
|
|
517
537
|
.example('赛事 对决 ZETA SunSister -i all')
|
|
538
|
+
.example('赛事 数据 求生者')
|
|
539
|
+
.example('赛事 数据 监管者选手 2026COA预选赛')
|
|
518
540
|
.option('i <模式>', '合并模式:team/player/all/none,留空用默认配置')
|
|
519
541
|
.action(async ({ session, options }, sub, p1, p2) => {
|
|
520
542
|
const subFn = String(sub || '').trim().toLowerCase()
|
|
@@ -525,10 +547,11 @@ module.exports = {
|
|
|
525
547
|
if (subFn === '选手') {
|
|
526
548
|
if (!p1 || !String(p1).trim()) return '请提供选手 id,格式:赛事 选手 <选手id>'
|
|
527
549
|
const target = String(p1).trim()
|
|
550
|
+
const notFoundText = '当前赛事数据系统未收录【' + target + '】相关数据,请检查选手id是否输入正确。目前仅支持使用选手英文id进行查询。'
|
|
528
551
|
try {
|
|
529
552
|
const result = await match.loadPlayerData(config, target, mode)
|
|
530
553
|
if (!result.data || (!result.data.hunter && !result.data.survivor)) {
|
|
531
|
-
return
|
|
554
|
+
return notFoundText
|
|
532
555
|
}
|
|
533
556
|
const width = cmdWidth(config, 'matchWidth')
|
|
534
557
|
const updateTime = await match.loadAnnounceTime(config)
|
|
@@ -537,6 +560,7 @@ module.exports = {
|
|
|
537
560
|
return updateTime ? [h.image(image, 'image/png'), '本页面数据上次更新时间:' + updateTime] : [h.image(image, 'image/png')]
|
|
538
561
|
} catch (e) {
|
|
539
562
|
ctx.logger('dwrgbwiki').warn('赛事查询失败: ' + (e && e.message ? e.message : e))
|
|
563
|
+
if (e && e.code === 'PLAYER_NOT_FOUND') return notFoundText
|
|
540
564
|
const msg = (e && e.message || '').includes('404')
|
|
541
565
|
? '未找到选手「' + target + '」的数据,请检查 id 是否正确(大小写、别名)'
|
|
542
566
|
: '赛事查询失败:' + (e && e.message ? e.message : e)
|
|
@@ -584,7 +608,49 @@ module.exports = {
|
|
|
584
608
|
}
|
|
585
609
|
}
|
|
586
610
|
|
|
587
|
-
|
|
611
|
+
if (subFn === '数据') {
|
|
612
|
+
// 参数可能带空格(赛事名里一般没有,但历史队伍名有),
|
|
613
|
+
// 所以直接从原文里切:去掉「赛事 数据」和 -i 选项,剩下第一个词是类型
|
|
614
|
+
let rest = String(session.content || '').trim()
|
|
615
|
+
.replace(/^[\s\S]*?赛事\s*/, '')
|
|
616
|
+
.replace(/^数据\s*/, '')
|
|
617
|
+
rest = rest.replace(/\s+-i\s+\S+/i, '').replace(/\s+--\S+/g, '').trim()
|
|
618
|
+
const parts = rest.split(/\s+/).filter(Boolean)
|
|
619
|
+
const typeArg = parts.shift() || ''
|
|
620
|
+
const tourArg = parts.join(' ')
|
|
621
|
+
if (!typeArg) return matchdata.TYPE_HELP
|
|
622
|
+
|
|
623
|
+
const width = cmdWidth(config, 'matchWidth')
|
|
624
|
+
try {
|
|
625
|
+
const res = await matchdata.buildTournamentData(
|
|
626
|
+
{ ...config, matchWidth: width }, typeArg, tourArg, mode)
|
|
627
|
+
const image = await capture(ctx, res.html, { ...config, width: res.width })
|
|
628
|
+
const tail = res.updateTime ? '本页面数据上次更新时间:' + res.updateTime : ''
|
|
629
|
+
return tail ? [h.image(image, 'image/png'), tail] : h.image(image, 'image/png')
|
|
630
|
+
} catch (e) {
|
|
631
|
+
ctx.logger('dwrgbwiki').warn('赛事数据查询失败: ' + (e && e.message ? e.message : e))
|
|
632
|
+
if (e.code === 'BAD_TYPE') return matchdata.TYPE_HELP
|
|
633
|
+
if (e.code === 'TOUR_AMBIGUOUS') return e.message
|
|
634
|
+
if (e.code === 'EMPTY_DATA') return e.message
|
|
635
|
+
if (e.code === 'NO_TOUR') {
|
|
636
|
+
const tips = (e.suggest && e.suggest.length) ? '\n\n最近更新的赛事:\n ' + e.suggest.join('\n ') : ''
|
|
637
|
+
return '请指定赛事名,例如:\n 赛事 数据 求生者 2026COA预选赛' + tips +
|
|
638
|
+
'\n\n也可以在插件配置里填「默认赛事」(matchDefaultTour),之后省略赛事名即可。'
|
|
639
|
+
}
|
|
640
|
+
if (e.code === 'TOUR_NOT_FOUND') {
|
|
641
|
+
const want = tourArg || config.matchDefaultTour || '(未配置默认赛事)'
|
|
642
|
+
const tips = (e.suggest && e.suggest.length)
|
|
643
|
+
? '\n\n最近的赛事:\n ' + e.suggest.join('\n ')
|
|
644
|
+
: ''
|
|
645
|
+
return '未找到赛事「' + want + '」。' +
|
|
646
|
+
'赛事名写成「赛段+阶段」的形式(如 2026COA预选赛),也可以只写阶段。' + tips +
|
|
647
|
+
'\n\n提示:可在插件配置里设置「默认赛事」,这样省略赛事名也能直接查。'
|
|
648
|
+
}
|
|
649
|
+
return errorImage(ctx, config, '赛事数据查询失败:' + (e && e.message ? e.message : e), '赛事')
|
|
650
|
+
}
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
return '请使用正确的格式:\n\n赛事 选手 <选手id> [-i 模式]\n赛事 对决 <队伍1> <队伍2> [-i 模式]\n赛事 数据 <类型> [赛事名] [-i 模式]\n\n示例:\n 赛事 选手 tian\n 赛事 对决 TE GG\n 赛事 数据 求生者'
|
|
588
654
|
})
|
|
589
655
|
|
|
590
656
|
ctx.command('角色 [角色名:text]', '列出该角色分类下的全部页面(图片)')
|
package/match.js
CHANGED
|
@@ -76,6 +76,13 @@ async function loadPlayerData(config, playerId, mergeMode) {
|
|
|
76
76
|
if (key.toLowerCase() === lower) { mainId = key; break }
|
|
77
77
|
}
|
|
78
78
|
}
|
|
79
|
+
// 选手未收录:index 中不存在该 id(大小写不敏感)时直接抛专用错误,
|
|
80
|
+
// 避免对不存在的文件发起请求而报出「Unexpected token '<'」之类的晦涩 JSON 解析错误
|
|
81
|
+
if (!index[mainId]) {
|
|
82
|
+
const err = new Error('PLAYER_NOT_FOUND:' + String(playerId))
|
|
83
|
+
err.code = 'PLAYER_NOT_FOUND'
|
|
84
|
+
throw err
|
|
85
|
+
}
|
|
79
86
|
// 收集候选文件:精确匹配 + 所有大小写变体
|
|
80
87
|
const candidates = new Set()
|
|
81
88
|
if (index[mainId]) candidates.add(index[mainId].file)
|