Skip to content

Commit aa7d536

Browse files
committed
feat: 生成抽卡记录图片
1 parent bdbde3f commit aa7d536

File tree

7 files changed

+363
-35
lines changed

7 files changed

+363
-35
lines changed

apps/gameCard.js

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,11 @@ export class gameCard extends plugin {
4949
)
5050
else await this.reply(`切换账号失败, 请检查索引是否正确`)
5151
}
52-
let data = await gameCardData.get(this.e, 'gameCardPns', this.e.user_id)
53-
if (!data) return false
52+
let data = await gameCardData.get(this.e, 'gameCardPns')
53+
if (!data) {
54+
kuroLogger.warn('战双卡片数据获取失败')
55+
await this.reply('卡片数据获取失败')
56+
return false}
5457
let img = await this.cachePns(data)
5558
await this.reply(img)
5659
}
@@ -91,22 +94,25 @@ export class gameCard extends plugin {
9194
)
9295
else await this.reply(`切换账号失败, 请检查索引是否正确`)
9396
}
94-
let data = await gameCardData.get(this.e, 'gameCardMc', this.e.user_id)
95-
if (!data) return false
97+
let data = await gameCardData.get(this.e, 'gameCardMc')
98+
if (!data) {
99+
kuroLogger.warn('战双卡片数据获取失败')
100+
await this.reply('卡片数据获取失败')
101+
return false}
96102
let img = await this.cacheMc(data)
97103
await this.reply(img)
98104
}
99105

100106
async cacheMc(data) {
101107
let tmp = md5(JSON.stringify(data))
102-
if (gameCard.mcCardData.md5 === tmp) {
103-
return gameCard.mcCardData.img
108+
if (this.mcCardData.md5 === tmp) {
109+
return this.mcCardData.img
104110
}
105111

106-
gameCard.mcCardData.img = await puppeteer.screenshot('gameCardMc', data)
107-
gameCard.mcCardData.md5 = tmp
112+
this.mcCardData.img = await puppeteer.screenshot('gameCardMc', data)
113+
this.mcCardData.md5 = tmp
108114

109-
return gameCard.mcCardData.img
115+
return this.mcCardData.img
110116
}
111117

112118
static mcCardData = {

apps/mcGacha.js

Lines changed: 78 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
import mcGachaData from '../model/mcGachaData.js'
22
import plugin from '../../../lib/plugins/plugin.js'
3+
import md5 from 'md5'
4+
import puppeteer from '../../../lib/puppeteer/puppeteer.js'
5+
import mcGachaCard from '../model/mcGachaCard.js'
6+
import kuroLogger from '../components/logger.js'
37

48
export class mcGacha extends plugin {
59
constructor() {
@@ -39,18 +43,83 @@ export class mcGacha extends plugin {
3943

4044
async mcGachaDataShow(e) {
4145
let gacha = new mcGachaData(e)
42-
await gacha.show()
43-
return true
46+
if(await gacha.check()){ // 通过检查, 可以生成抽卡分析
47+
// 从消息中提取卡池类型
48+
let msg = this.e.msg.replace(/#| /g, '').replace(/||||/g, '')
49+
let gachaType = 0
50+
let cardPoolName = ''
51+
switch (msg) {
52+
case '抽卡':
53+
case '角色':
54+
case 'up':
55+
case '抽奖':
56+
case '角色活动':
57+
case '角色up':
58+
gachaType = 1
59+
cardPoolName = '角色活动唤取'
60+
break
61+
case '武器':
62+
case '武器活动':
63+
case '武器up':
64+
gachaType = 2
65+
cardPoolName = '武器活动唤取'
66+
break
67+
case '常驻':
68+
case '角色常驻':
69+
gachaType = 3
70+
cardPoolName = '角色常驻唤取'
71+
break
72+
case '武器常驻':
73+
gachaType = 4
74+
cardPoolName = '武器常驻唤取'
75+
break
76+
case '新手':
77+
gachaType = 5
78+
cardPoolName = '新手唤取'
79+
break
80+
case '新手自选':
81+
case '自选':
82+
gachaType = 6
83+
cardPoolName = '新手自选唤取'
84+
break
85+
default:
86+
gachaType = 1
87+
cardPoolName = '角色活动唤取'
88+
}
89+
let data = await mcGachaCard.get(this.e, gachaType, cardPoolName)
90+
if (!data) {
91+
kuroLogger.warn('抽卡记录卡片数据获取失败')
92+
return false}
93+
if (typeof data === 'string') {
94+
await this.reply(data)
95+
return false
96+
}
97+
let img = await this.cache(data)
98+
await this.reply(img)
99+
}
100+
return false
101+
}
102+
103+
async cache(data) {
104+
let tmp = md5(JSON.stringify(data))
105+
if (mcGacha.mcGachaCardData.md5 === tmp) {
106+
return mcGacha.mcGachaCardData.img
107+
}
108+
109+
mcGacha.mcGachaCardData.img = await puppeteer.screenshot('mcGachaRecord', data)
110+
mcGacha.mcGachaCardData.md5 = tmp
111+
112+
return mcGacha.mcGachaCardData.img
113+
}
114+
115+
static mcGachaCardData = {
116+
md5: '',
117+
img: '',
44118
}
45119

46120
async mcGachaHelp(e) {
47121
e.reply(
48-
`可通过以下两种方式获取抽卡记录:
49-
#鸣潮本地获取抽卡记录
50-
- 在本地访问链接获取抽卡记录, 快速但是无法自动更新
51-
#鸣潮上传抽卡记录链接
52-
- 通过日志中的抽卡记录链接上传, 繁琐但是一次获取长期有效
53-
请发送相应指令查看帮助` // 抽卡链接有效期
122+
`可通过以下两种方式获取抽卡记录: \n#鸣潮本地获取抽卡记录 \n - 在本地访问链接获取抽卡记录, 快速但是无法自动更新 \n#鸣潮上传抽卡记录链接 \n - 通过日志中的抽卡记录链接上传, 繁琐但是一次获取长期有效 \n请发送相应指令查看帮助` // TODO: 抽卡链接有效期
54123
)
55124
return true
56125
}
@@ -83,7 +152,7 @@ export class mcGacha extends plugin {
83152
let gacha = new mcGachaData(e)
84153
let gachaRecord = await gacha.get(e.msg, e.user_id)
85154
if (typeof gachaRecord === 'string') {
86-
e.reply(`抽卡记录更新失败: \n${gachaRecord}`)
155+
e.reply(`抽卡记录更新失败: \n${gachaRecord} \n请检查链接是否正确 `)
87156
return true
88157
} else {
89158
let failedReason = await gacha.update(e.user_id, gachaRecord)

model/mcGachaCard.js

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
import kuroLogger from '../components/logger.js'
2+
import {
3+
mcGachaDataPath,
4+
pluginName,
5+
pluginVer,
6+
resPath,
7+
_ResPath,
8+
} from '../data/system/pluginConstants.js'
9+
import mcGachaData from './mcGachaData.js'
10+
import userConfig from './userConfig.js'
11+
12+
export default class mcGachaCard {
13+
constructor(e, gachaType) {
14+
this.e = e
15+
}
16+
17+
/** 获取抽卡记录卡片数据
18+
* @param {object} e - 消息对象
19+
* @param {number} gachaType - 抽卡类型
20+
* @returns {object|string} - 抽卡记录卡片数据 json, 失败返回错误信息 str
21+
*/
22+
static async get(e, gachaType, cardPoolName) {
23+
if (typeof gachaType !== 'number' || gachaType > 6 || gachaType < 1) return '抽卡类型错误'
24+
let gacha = new mcGachaData(e)
25+
let user = new userConfig()
26+
let OriginGachaRecord = await gacha.getUigfRecord(e.user_id, (await user.getCurGameUidLocal(e.user_id, 3))?.gameUid)
27+
if (typeof OriginGachaRecord !== 'object' || OriginGachaRecord.length === 0) {
28+
kuroLogger.warn(`抽卡记录卡片数据获取失败: ${OriginGachaRecord}`)
29+
await e.reply(`抽卡记录卡片数据获取失败: ${OriginGachaRecord}`)
30+
return `抽卡记录卡片数据获取失败: ${OriginGachaRecord}`
31+
}
32+
33+
// 提取符合 gachaType 的记录
34+
let gachaRecord = []
35+
for (let i = 0; i < OriginGachaRecord.list.length; i++) {
36+
if (OriginGachaRecord.list[i].gacha_type == gachaType.toString()) {
37+
gachaRecord.push(OriginGachaRecord.list[i])
38+
}
39+
}
40+
// 将 gachaRecord 倒序, 以便分析金卡所需抽数
41+
gachaRecord.reverse()
42+
43+
// 分析每次出金卡所需抽数
44+
let goldCardRecord = []
45+
let lastGoldIndex = -1
46+
for (let i = 0; i < gachaRecord.length; i++) {
47+
if (gachaRecord[i].rank_type === '5') {
48+
goldCardRecord.push({
49+
id: gachaRecord[i].id,
50+
gachaType: gachaRecord[i].gacha_type,
51+
itemId: gachaRecord[i].item_id,
52+
itemCount: gachaRecord[i].count,
53+
itemName: gachaRecord[i].name,
54+
itemType: gachaRecord[i].item_type,
55+
itemRank: gachaRecord[i].rank_type,
56+
time: gachaRecord[i].time,
57+
totalGachaTimes: i + 1,
58+
thisCardCost: i - lastGoldIndex,
59+
})
60+
lastGoldIndex = i
61+
}
62+
63+
if (i === gachaRecord.length - 1 && i !== lastGoldIndex) { // 最后一次未出金卡的抽数统计
64+
goldCardRecord.push({
65+
id: gachaRecord[i].id,
66+
gachaType: gachaRecord[i].gacha_type,
67+
itemId: '-1',
68+
itemCount: '-1',
69+
itemName: '?',
70+
itemType: '-1',
71+
itemRank: '-1',
72+
time: gachaRecord[i].time,
73+
totalGachaTimes: i + 1,
74+
thisCardCost: i - lastGoldIndex,
75+
})
76+
}
77+
}
78+
79+
// 再次倒序, 把新的记录放在最前面
80+
goldCardRecord.reverse()
81+
82+
kuroLogger.debug('分析后的抽卡记录:', JSON.stringify(goldCardRecord))
83+
84+
// return JSON.stringify(goldCardRecord)
85+
86+
let ret = {
87+
tplFile: `${resPath}/html/mcGachaRecord/index.html`,
88+
goldCardRecord,
89+
cardPoolName,
90+
pluResPath: _ResPath,
91+
pluginName,
92+
pluginVer,
93+
}
94+
if (!ret) {
95+
await e.reply(`抽卡记录卡片数据获取失败: 未知错误`)
96+
return '抽卡记录卡片数据获取失败: 未知错误'
97+
}
98+
99+
return ret
100+
101+
}
102+
}

model/mcGachaData.js

Lines changed: 38 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,10 @@ export default class mcGachaData {
2020
}
2121
}
2222

23-
async show() {
24-
let msg = this.e.msg.replace(/#| /g, '').replace(/|||/g, '')
25-
23+
/** 检查是否可以生成抽卡记录
24+
* @returns {boolean} 是否通过检查, 没通过检查就不生成了
25+
*/
26+
async check() {
2627
const tokenData = await getToken(this.e.user_id)
2728
kuroLogger.debug(
2829
`QQ ${this.e.user_id} 的 tokenData: ${JSON.stringify(tokenData)}`
@@ -40,29 +41,29 @@ export default class mcGachaData {
4041

4142
// 先检查本地是否既没有抽卡记录也没有抽卡链接, 如果没有就提示获取抽卡记录
4243
if (!(await this.exist(this.e.user_id, gameUid)) && !gachaLink) {
43-
this.e.reply(
44+
await this.e.reply(
4445
`QQ ${this.e.user_id} 的游戏 uid ${gameUid} 暂未获取抽卡记录\n请发送 #鸣潮抽卡记录帮助 以获取记录`
4546
)
46-
return
47+
return false
4748
}
4849

4950
// 然后检查是否是通过链接上传的信息, 如果是链接上传就更新再生成, 如果是本地上传就直接生成
5051
if (gachaLink) {
51-
this.e.reply(
52+
await this.e.reply(
5253
`QQ ${this.e.user_id} 的游戏 uid ${gameUid} 本地存在抽卡链接, 尝试更新抽卡记录...`
5354
)
5455
let gachaRecord = await this.get(gachaLink, this.e.user_id)
5556
if (typeof gachaRecord === 'string') {
5657
// 如果记录更新失败, 进行提示; 如果更新成功, 不提示直接进入生成
57-
this.e.reply(
58+
await this.e.reply(
5859
`QQ ${this.e.user_id} 的游戏 uid ${gameUid} 更新抽卡记录失败: \n${failedReason}\n将展示历史抽卡记录`
5960
)
6061
} else {
6162
// 更新成功, 存入本地
6263
await this.update(this.e.user_id, gachaRecord)
6364
}
6465
} else {
65-
this.e.reply(
66+
await this.e.reply(
6667
`QQ ${this.e.user_id} 的游戏 uid ${gameUid} 通过本地上传的抽卡记录, 将展示历史抽卡记录`
6768
)
6869
}
@@ -72,17 +73,12 @@ export default class mcGachaData {
7273
} else {
7374
// 没绑定当然也能获取 ,但是警告一下获取不到部分信息
7475
// TODO: 把这个放到绑定抽卡链接的提示吧
75-
// this.e.reply(
76+
// await this.e.reply(
7677
// `QQ ${this.e.user_id} 暂未绑定 token, 将无法获取到部分额外信息, 建议发送 #库洛验证码登录 绑定 token`
7778
// )
7879
}
7980

80-
// 开始生成抽卡记录
81-
this.generateAndReply()
82-
}
83-
84-
async generateAndReply() {
85-
// TODO
81+
return true
8682
}
8783

8884
/** 通过抽卡链接获取抽卡记录
@@ -159,7 +155,7 @@ export default class mcGachaData {
159155
kuroLogger.debug(
160156
`QQ ${qq} 的抽卡链接 ${link} 获取失败: ${rsp_mcGachaRecord}`
161157
)
162-
return `QQ ${qq} 的抽卡链接 ${link} 获取失败: \n${rsp_mcGachaRecord}`
158+
return `获取失败: ${rsp_mcGachaRecord}`
163159
}
164160

165161
// 完成测试, 保存记录到本地
@@ -342,4 +338,30 @@ export default class mcGachaData {
342338
return null
343339
}
344340
}
341+
342+
/** 以原格式输出抽卡记录
343+
* @param {number} qq QQ
344+
* @param {number} gameUid 游戏 uid, 如果传入 0 则输出第一个 uid
345+
* @returns {object|string} 成功则返回原始 UIGF 格式的抽卡记录, 失败则返回 str 原因
346+
*/
347+
async getUigfRecord(qq, gameUid) {
348+
// gameUid 无效时获取第一个 uid
349+
if (!gameUid) {
350+
gameUid = this.exist(qq, 0)
351+
if (!gameUid) {
352+
return '未找到抽卡记录'
353+
}
354+
}
355+
let path = `${mcGachaDataPath}/${qq}-${gameUid}.json`
356+
if (!fs.existsSync(path)) {
357+
return '未找到抽卡记录'
358+
}
359+
// 使用 try catch 捕获错误
360+
try {
361+
let data = fs.readFileSync(path)
362+
return JSON.parse(data)
363+
} catch (error) {
364+
return '提取抽卡记录失败: ' + error.message
365+
}
366+
}
345367
}

resources/html/gameCardMc/index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
<div class="container" id="container">
1313
<div class="head-box">
1414
<div class="title" style="color: white;">鸣潮卡片 - 库洛插件</div>
15-
<div class="label" style="color: white;">Handmade With ❤️ by TomyJan.</div>
15+
<div class="label" style="color: white;">Handmade With ❤️ by TomyJan. | 当前页面正在绝赞监修中</div>
1616
</div>
1717

1818

0 commit comments

Comments
 (0)