diff --git a/apps/gameCard.js b/apps/gameCard.js index c1918dd..eeabbdb 100644 --- a/apps/gameCard.js +++ b/apps/gameCard.js @@ -49,8 +49,11 @@ export class gameCard extends plugin { ) else await this.reply(`切换账号失败, 请检查索引是否正确`) } - let data = await gameCardData.get(this.e, 'gameCardPns', this.e.user_id) - if (!data) return false + let data = await gameCardData.get(this.e, 'gameCardPns') + if (!data) { + kuroLogger.warn('战双卡片数据获取失败') + await this.reply('卡片数据获取失败') + return false} let img = await this.cachePns(data) await this.reply(img) } @@ -91,22 +94,25 @@ export class gameCard extends plugin { ) else await this.reply(`切换账号失败, 请检查索引是否正确`) } - let data = await gameCardData.get(this.e, 'gameCardMc', this.e.user_id) - if (!data) return false + let data = await gameCardData.get(this.e, 'gameCardMc') + if (!data) { + kuroLogger.warn('战双卡片数据获取失败') + await this.reply('卡片数据获取失败') + return false} let img = await this.cacheMc(data) await this.reply(img) } async cacheMc(data) { let tmp = md5(JSON.stringify(data)) - if (gameCard.mcCardData.md5 === tmp) { - return gameCard.mcCardData.img + if (this.mcCardData.md5 === tmp) { + return this.mcCardData.img } - gameCard.mcCardData.img = await puppeteer.screenshot('gameCardMc', data) - gameCard.mcCardData.md5 = tmp + this.mcCardData.img = await puppeteer.screenshot('gameCardMc', data) + this.mcCardData.md5 = tmp - return gameCard.mcCardData.img + return this.mcCardData.img } static mcCardData = { diff --git a/apps/mcGacha.js b/apps/mcGacha.js index 63e7aa8..b35359a 100644 --- a/apps/mcGacha.js +++ b/apps/mcGacha.js @@ -1,5 +1,9 @@ import mcGachaData from '../model/mcGachaData.js' import plugin from '../../../lib/plugins/plugin.js' +import md5 from 'md5' +import puppeteer from '../../../lib/puppeteer/puppeteer.js' +import mcGachaCard from '../model/mcGachaCard.js' +import kuroLogger from '../components/logger.js' export class mcGacha extends plugin { constructor() { @@ -39,18 +43,83 @@ export class mcGacha extends plugin { async mcGachaDataShow(e) { let gacha = new mcGachaData(e) - await gacha.show() - return true + if(await gacha.check()){ // 通过检查, 可以生成抽卡分析 + // 从消息中提取卡池类型 + let msg = this.e.msg.replace(/#| /g, '').replace(/鸣潮|记录|唤取|分析|池/g, '') + let gachaType = 0 + let cardPoolName = '' + switch (msg) { + case '抽卡': + case '角色': + case 'up': + case '抽奖': + case '角色活动': + case '角色up': + gachaType = 1 + cardPoolName = '角色活动唤取' + break + case '武器': + case '武器活动': + case '武器up': + gachaType = 2 + cardPoolName = '武器活动唤取' + break + case '常驻': + case '角色常驻': + gachaType = 3 + cardPoolName = '角色常驻唤取' + break + case '武器常驻': + gachaType = 4 + cardPoolName = '武器常驻唤取' + break + case '新手': + gachaType = 5 + cardPoolName = '新手唤取' + break + case '新手自选': + case '自选': + gachaType = 6 + cardPoolName = '新手自选唤取' + break + default: + gachaType = 1 + cardPoolName = '角色活动唤取' + } + let data = await mcGachaCard.get(this.e, gachaType, cardPoolName) + if (!data) { + kuroLogger.warn('抽卡记录卡片数据获取失败') + return false} + if (typeof data === 'string') { + await this.reply(data) + return false + } + let img = await this.cache(data) + await this.reply(img) + } + return false + } + + async cache(data) { + let tmp = md5(JSON.stringify(data)) + if (mcGacha.mcGachaCardData.md5 === tmp) { + return mcGacha.mcGachaCardData.img + } + + mcGacha.mcGachaCardData.img = await puppeteer.screenshot('mcGachaRecord', data) + mcGacha.mcGachaCardData.md5 = tmp + + return mcGacha.mcGachaCardData.img + } + + static mcGachaCardData = { + md5: '', + img: '', } async mcGachaHelp(e) { e.reply( - `可通过以下两种方式获取抽卡记录: - #鸣潮本地获取抽卡记录 - - 在本地访问链接获取抽卡记录, 快速但是无法自动更新 - #鸣潮上传抽卡记录链接 - - 通过日志中的抽卡记录链接上传, 繁琐但是一次获取长期有效 - 请发送相应指令查看帮助` // 抽卡链接有效期 + `可通过以下两种方式获取抽卡记录: \n#鸣潮本地获取抽卡记录 \n - 在本地访问链接获取抽卡记录, 快速但是无法自动更新 \n#鸣潮上传抽卡记录链接 \n - 通过日志中的抽卡记录链接上传, 繁琐但是一次获取长期有效 \n请发送相应指令查看帮助` // TODO: 抽卡链接有效期 ) return true } @@ -83,7 +152,7 @@ export class mcGacha extends plugin { let gacha = new mcGachaData(e) let gachaRecord = await gacha.get(e.msg, e.user_id) if (typeof gachaRecord === 'string') { - e.reply(`抽卡记录更新失败: \n${gachaRecord}`) + e.reply(`抽卡记录更新失败: \n${gachaRecord} \n请检查链接是否正确 `) return true } else { let failedReason = await gacha.update(e.user_id, gachaRecord) diff --git a/model/mcGachaCard.js b/model/mcGachaCard.js new file mode 100644 index 0000000..eafbb60 --- /dev/null +++ b/model/mcGachaCard.js @@ -0,0 +1,102 @@ +import kuroLogger from '../components/logger.js' +import { + mcGachaDataPath, + pluginName, + pluginVer, + resPath, + _ResPath, +} from '../data/system/pluginConstants.js' +import mcGachaData from './mcGachaData.js' +import userConfig from './userConfig.js' + +export default class mcGachaCard { + constructor(e, gachaType) { + this.e = e + } + +/** 获取抽卡记录卡片数据 + * @param {object} e - 消息对象 + * @param {number} gachaType - 抽卡类型 + * @returns {object|string} - 抽卡记录卡片数据 json, 失败返回错误信息 str + */ + static async get(e, gachaType, cardPoolName) { + if (typeof gachaType !== 'number' || gachaType > 6 || gachaType < 1) return '抽卡类型错误' + let gacha = new mcGachaData(e) + let user = new userConfig() + let OriginGachaRecord = await gacha.getUigfRecord(e.user_id, (await user.getCurGameUidLocal(e.user_id, 3))?.gameUid) + if (typeof OriginGachaRecord !== 'object' || OriginGachaRecord.length === 0) { + kuroLogger.warn(`抽卡记录卡片数据获取失败: ${OriginGachaRecord}`) + await e.reply(`抽卡记录卡片数据获取失败: ${OriginGachaRecord}`) + return `抽卡记录卡片数据获取失败: ${OriginGachaRecord}` + } + + // 提取符合 gachaType 的记录 + let gachaRecord = [] + for (let i = 0; i < OriginGachaRecord.list.length; i++) { + if (OriginGachaRecord.list[i].gacha_type == gachaType.toString()) { + gachaRecord.push(OriginGachaRecord.list[i]) + } + } + // 将 gachaRecord 倒序, 以便分析金卡所需抽数 + gachaRecord.reverse() + + // 分析每次出金卡所需抽数 + let goldCardRecord = [] + let lastGoldIndex = -1 + for (let i = 0; i < gachaRecord.length; i++) { + if (gachaRecord[i].rank_type === '5') { + goldCardRecord.push({ + id: gachaRecord[i].id, + gachaType: gachaRecord[i].gacha_type, + itemId: gachaRecord[i].item_id, + itemCount: gachaRecord[i].count, + itemName: gachaRecord[i].name, + itemType: gachaRecord[i].item_type, + itemRank: gachaRecord[i].rank_type, + time: gachaRecord[i].time, + totalGachaTimes: i + 1, + thisCardCost: i - lastGoldIndex, + }) + lastGoldIndex = i + } + + if (i === gachaRecord.length - 1 && i !== lastGoldIndex) { // 最后一次未出金卡的抽数统计 + goldCardRecord.push({ + id: gachaRecord[i].id, + gachaType: gachaRecord[i].gacha_type, + itemId: '-1', + itemCount: '-1', + itemName: '?', + itemType: '-1', + itemRank: '-1', + time: gachaRecord[i].time, + totalGachaTimes: i + 1, + thisCardCost: i - lastGoldIndex, + }) + } + } + + // 再次倒序, 把新的记录放在最前面 + goldCardRecord.reverse() + + kuroLogger.debug('分析后的抽卡记录:', JSON.stringify(goldCardRecord)) + + // return JSON.stringify(goldCardRecord) + + let ret = { + tplFile: `${resPath}/html/mcGachaRecord/index.html`, + goldCardRecord, + cardPoolName, + pluResPath: _ResPath, + pluginName, + pluginVer, + } + if (!ret) { + await e.reply(`抽卡记录卡片数据获取失败: 未知错误`) + return '抽卡记录卡片数据获取失败: 未知错误' + } + + return ret + + } +} diff --git a/model/mcGachaData.js b/model/mcGachaData.js index c948049..49734f5 100644 --- a/model/mcGachaData.js +++ b/model/mcGachaData.js @@ -20,9 +20,10 @@ export default class mcGachaData { } } - async show() { - let msg = this.e.msg.replace(/#| /g, '').replace(/记录|唤取|分析|池/g, '') - +/** 检查是否可以生成抽卡记录 + * @returns {boolean} 是否通过检查, 没通过检查就不生成了 + */ + async check() { const tokenData = await getToken(this.e.user_id) kuroLogger.debug( `QQ ${this.e.user_id} 的 tokenData: ${JSON.stringify(tokenData)}` @@ -40,21 +41,21 @@ export default class mcGachaData { // 先检查本地是否既没有抽卡记录也没有抽卡链接, 如果没有就提示获取抽卡记录 if (!(await this.exist(this.e.user_id, gameUid)) && !gachaLink) { - this.e.reply( + await this.e.reply( `QQ ${this.e.user_id} 的游戏 uid ${gameUid} 暂未获取抽卡记录\n请发送 #鸣潮抽卡记录帮助 以获取记录` ) - return + return false } // 然后检查是否是通过链接上传的信息, 如果是链接上传就更新再生成, 如果是本地上传就直接生成 if (gachaLink) { - this.e.reply( + await this.e.reply( `QQ ${this.e.user_id} 的游戏 uid ${gameUid} 本地存在抽卡链接, 尝试更新抽卡记录...` ) let gachaRecord = await this.get(gachaLink, this.e.user_id) if (typeof gachaRecord === 'string') { // 如果记录更新失败, 进行提示; 如果更新成功, 不提示直接进入生成 - this.e.reply( + await this.e.reply( `QQ ${this.e.user_id} 的游戏 uid ${gameUid} 更新抽卡记录失败: \n${failedReason}\n将展示历史抽卡记录` ) } else { @@ -62,7 +63,7 @@ export default class mcGachaData { await this.update(this.e.user_id, gachaRecord) } } else { - this.e.reply( + await this.e.reply( `QQ ${this.e.user_id} 的游戏 uid ${gameUid} 通过本地上传的抽卡记录, 将展示历史抽卡记录` ) } @@ -72,17 +73,12 @@ export default class mcGachaData { } else { // 没绑定当然也能获取 ,但是警告一下获取不到部分信息 // TODO: 把这个放到绑定抽卡链接的提示吧 - // this.e.reply( + // await this.e.reply( // `QQ ${this.e.user_id} 暂未绑定 token, 将无法获取到部分额外信息, 建议发送 #库洛验证码登录 绑定 token` // ) } - // 开始生成抽卡记录 - this.generateAndReply() - } - - async generateAndReply() { - // TODO + return true } /** 通过抽卡链接获取抽卡记录 @@ -159,7 +155,7 @@ export default class mcGachaData { kuroLogger.debug( `QQ ${qq} 的抽卡链接 ${link} 获取失败: ${rsp_mcGachaRecord}` ) - return `QQ ${qq} 的抽卡链接 ${link} 获取失败: \n${rsp_mcGachaRecord}` + return `获取失败: ${rsp_mcGachaRecord}` } // 完成测试, 保存记录到本地 @@ -342,4 +338,30 @@ export default class mcGachaData { return null } } + +/** 以原格式输出抽卡记录 + * @param {number} qq QQ + * @param {number} gameUid 游戏 uid, 如果传入 0 则输出第一个 uid + * @returns {object|string} 成功则返回原始 UIGF 格式的抽卡记录, 失败则返回 str 原因 + */ + async getUigfRecord(qq, gameUid) { + // gameUid 无效时获取第一个 uid + if (!gameUid) { + gameUid = this.exist(qq, 0) + if (!gameUid) { + return '未找到抽卡记录' + } + } + let path = `${mcGachaDataPath}/${qq}-${gameUid}.json` + if (!fs.existsSync(path)) { + return '未找到抽卡记录' + } + // 使用 try catch 捕获错误 + try { + let data = fs.readFileSync(path) + return JSON.parse(data) + } catch (error) { + return '提取抽卡记录失败: ' + error.message + } + } } diff --git a/resources/html/gameCardMc/index.html b/resources/html/gameCardMc/index.html index c31d091..da335af 100644 --- a/resources/html/gameCardMc/index.html +++ b/resources/html/gameCardMc/index.html @@ -12,7 +12,7 @@