From d0bdca6c286987dd3df9e0a9ede3cefb9fa1e4e7 Mon Sep 17 00:00:00 2001 From: touchscale <11134128+touchscale@user.noreply.gitee.com> Date: Wed, 10 May 2023 16:34:17 +0000 Subject: [PATCH 01/33] =?UTF-8?q?icqq=E7=89=88=E6=9C=AC=E5=8D=87=E7=BA=A7?= =?UTF-8?q?=EF=BC=8C=E4=BF=AE=E5=A4=8Dnode16=E4=BB=A5=E4=B8=8A=E7=89=88?= =?UTF-8?q?=E6=9C=AC=E6=97=A0=E6=B3=95=E6=AD=A3=E5=B8=B8=E4=BD=BF=E7=94=A8?= =?UTF-8?q?=E9=97=AE=E9=A2=98=EF=BC=8C=E4=BF=AE=E5=A4=8Dnode16=E4=BB=A5?= =?UTF-8?q?=E4=B8=8A=E7=89=88=E6=9C=AC=E6=97=A0=E6=B3=95=E6=AD=A3=E5=B8=B8?= =?UTF-8?q?=E4=BD=BF=E7=94=A8=E9=97=AE=E9=A2=98=EF=BC=8C=E6=9B=B4=E6=96=B0?= =?UTF-8?q?=E5=85=B6=E4=BB=96=E4=BE=9D=E8=B5=96(=20(=E6=9B=B4=E6=96=B0?= =?UTF-8?q?=E5=90=8E=E9=9C=80=E8=A6=81pnpm=20install=E5=8D=87=E7=BA=A7?= =?UTF-8?q?=E4=BE=9D=E8=B5=96=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: touchscale <11134128+touchscale@user.noreply.gitee.com> --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 09ae8ea..e275059 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,7 @@ "chalk": "^5.2.0", "chokidar": "^3.5.3", "https-proxy-agent": "5.0.1", - "icqq": "0.3.1", + "icqq": "0.3.5", "image-size": "^1.0.2", "inquirer": "^8.2.5", "lodash": "^4.17.21", @@ -33,7 +33,7 @@ "node-xlsx": "^0.21.2", "oicq": "^2.3.1", "pm2": "^5.3.0", - "puppeteer": "^19.11.1", + "puppeteer": "^20.1.2", "redis": "^4.6.6", "sequelize": "^6.31.1", "sqlite3": "^5.1.6", From f0d9a5e34e85132c466d784bdb6c627e6e8ac026 Mon Sep 17 00:00:00 2001 From: touchscale <11134128+touchscale@user.noreply.gitee.com> Date: Wed, 10 May 2023 16:39:53 +0000 Subject: [PATCH 02/33] update package.json. Signed-off-by: touchscale <11134128+touchscale@user.noreply.gitee.com> --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e275059..7b49816 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,7 @@ "chalk": "^5.2.0", "chokidar": "^3.5.3", "https-proxy-agent": "5.0.1", - "icqq": "0.3.5", + "icqq": "0.3.6", "image-size": "^1.0.2", "inquirer": "^8.2.5", "lodash": "^4.17.21", From 6cc86cc36be926d1247427e7e31c703727a5404b Mon Sep 17 00:00:00 2001 From: touchscale <11134128+touchscale@user.noreply.gitee.com> Date: Wed, 10 May 2023 16:41:19 +0000 Subject: [PATCH 03/33] update package.json. Signed-off-by: touchscale <11134128+touchscale@user.noreply.gitee.com> --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7b49816..1f107bd 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,7 @@ "chalk": "^5.2.0", "chokidar": "^3.5.3", "https-proxy-agent": "5.0.1", - "icqq": "0.3.6", + "icqq": "^0.3.6", "image-size": "^1.0.2", "inquirer": "^8.2.5", "lodash": "^4.17.21", From f0a8d5114dcfc7a3499dda9c4949e928530ec30d Mon Sep 17 00:00:00 2001 From: touchscale <11134128+touchscale@user.noreply.gitee.com> Date: Thu, 11 May 2023 03:41:02 +0000 Subject: [PATCH 04/33] update package.json. Signed-off-by: touchscale <11134128+touchscale@user.noreply.gitee.com> --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1f107bd..21bd854 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,7 @@ "chalk": "^5.2.0", "chokidar": "^3.5.3", "https-proxy-agent": "5.0.1", - "icqq": "^0.3.6", + "icqq": "^0.3.7", "image-size": "^1.0.2", "inquirer": "^8.2.5", "lodash": "^4.17.21", From b9191157520f931576d5e16a774bc82ceb7aaeaa Mon Sep 17 00:00:00 2001 From: touchscale <11134128+touchscale@user.noreply.gitee.com> Date: Thu, 11 May 2023 05:49:18 +0000 Subject: [PATCH 05/33] update package.json. Signed-off-by: touchscale <11134128+touchscale@user.noreply.gitee.com> --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 21bd854..d6027a3 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,7 @@ "chalk": "^5.2.0", "chokidar": "^3.5.3", "https-proxy-agent": "5.0.1", - "icqq": "^0.3.7", + "icqq": "^0.3.8", "image-size": "^1.0.2", "inquirer": "^8.2.5", "lodash": "^4.17.21", From 52dc948e93c0f315f8011de41ce1726183a4ef86 Mon Sep 17 00:00:00 2001 From: touchscale <11134128+touchscale@user.noreply.gitee.com> Date: Thu, 11 May 2023 06:13:17 +0000 Subject: [PATCH 07/33] update package.json. Signed-off-by: touchscale <11134128+touchscale@user.noreply.gitee.com> --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d6027a3..683ce37 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,7 @@ "chalk": "^5.2.0", "chokidar": "^3.5.3", "https-proxy-agent": "5.0.1", - "icqq": "^0.3.8", + "icqq": "^0.3.9", "image-size": "^1.0.2", "inquirer": "^8.2.5", "lodash": "^4.17.21", From 1dd220e505f50e40335a97989d584e0d5a79bac9 Mon Sep 17 00:00:00 2001 From: Rainbow <9510289+rainbowwarmth@user.noreply.gitee.com> Date: Thu, 11 May 2023 08:09:54 +0000 Subject: [PATCH 08/33] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E4=BA=86=E5=BC=80?= =?UTF-8?q?=E5=90=AF=E9=93=81=E9=81=93=E5=85=AC=E5=91=8A=E6=8E=A8=E9=80=81?= =?UTF-8?q?=E4=BC=9A=E8=A6=86=E7=9B=96=E5=8E=9F=E7=A5=9E=E5=85=AC=E5=91=8A?= =?UTF-8?q?=E6=8E=A8=E9=80=81=E7=9A=84=E6=84=8F=E5=A4=96=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rainbow <9510289+rainbowwarmth@user.noreply.gitee.com> --- plugins/genshin/apps/mysNews.js | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/plugins/genshin/apps/mysNews.js b/plugins/genshin/apps/mysNews.js index 8ca4cca..daa3f52 100644 --- a/plugins/genshin/apps/mysNews.js +++ b/plugins/genshin/apps/mysNews.js @@ -60,12 +60,20 @@ export class mysNews extends plugin { this.file = './plugins/genshin/config/mys.pushNews.yaml' /** 定时任务 */ - this.task = { - cron: gsCfg.getConfig('mys', 'pushNews').pushTime, - name: '米游社公告推送任务', - fnc: () => this.mysNewsTask(), - log: false - } + this.task = [ + { + cron: gsCfg.getConfig('mys', 'pushNews').pushTime, + name: '米游社公告推送任务', + fnc: () => this.mysNewsTask(), + log: false + }, + { + cron: gsCfg.getConfig('mys', 'pushNews').pushTime, + name: '崩坏星穹铁道公告推送任务', + fnc: () => this.srmysNewsTask(), + log: false + } + ] } async init () { @@ -87,7 +95,7 @@ export class mysNews extends plugin { } async mysNewsTask () { - let mysNews = new srNews(this.e) + let mysNews = new MysNews(this.e) await mysNews.mysNewsTask() } From bf040b15e229bbff97d79a1ec1268e93a3456b68 Mon Sep 17 00:00:00 2001 From: touchscale <11134128+touchscale@user.noreply.gitee.com> Date: Thu, 11 May 2023 08:40:28 +0000 Subject: [PATCH 09/33] update package.json. Signed-off-by: touchscale <11134128+touchscale@user.noreply.gitee.com> --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 683ce37..1ea1feb 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,7 @@ "chalk": "^5.2.0", "chokidar": "^3.5.3", "https-proxy-agent": "5.0.1", - "icqq": "^0.3.9", + "icqq": "^0.3.10", "image-size": "^1.0.2", "inquirer": "^8.2.5", "lodash": "^4.17.21", From c17670701a8b8664ed77447a12d516242d54d7a5 Mon Sep 17 00:00:00 2001 From: touchscale <11134128+touchscale@user.noreply.gitee.com> Date: Thu, 11 May 2023 12:43:18 +0000 Subject: [PATCH 10/33] update lib/config/config.js. Signed-off-by: touchscale <11134128+touchscale@user.noreply.gitee.com> --- lib/config/config.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/lib/config/config.js b/lib/config/config.js index 41898cd..0f0a64a 100644 --- a/lib/config/config.js +++ b/lib/config/config.js @@ -62,6 +62,10 @@ class Cfg { return this.getConfig('renderer'); } + get notice() { + return this.getConfig('notice'); + } + /** 主人qq */ get masterQQ () { let masterQQ = this.getConfig('other').masterQQ || [] @@ -99,6 +103,13 @@ class Cfg { return { ...def, ...config } } + /** notice配置 */ + getOther () { + let def = this.getdefSet('notice') + let config = this.getConfig('notice') + return { ...def, ...config } + } + /** * @param app 功能 * @param name 配置文件名称 From 8d7b457a9a6cb16cfd7c92ec9ce1016e130631c6 Mon Sep 17 00:00:00 2001 From: Rrrrrrray <28804884+Rrrrrrray@users.noreply.github.com> Date: Fri, 12 May 2023 19:46:32 +0800 Subject: [PATCH 11/33] =?UTF-8?q?fix=EF=BC=9A=E6=98=9F=E9=93=81=E6=8A=BD?= =?UTF-8?q?=E5=8D=A1=E9=93=BE=E6=8E=A5=E6=97=A0=E6=B3=95=E8=AF=86=E5=88=AB?= =?UTF-8?q?bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/plugins/loader.js | 3 ++- plugins/genshin/model/gachaLog.js | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/plugins/loader.js b/lib/plugins/loader.js index e7865b2..f8393ab 100644 --- a/lib/plugins/loader.js +++ b/lib/plugins/loader.js @@ -359,7 +359,8 @@ class PluginsLoader { // 判断是否是星铁命令,若是星铁命令则标准化处理 // e.isSr = true,且命令标准化为 #星铁 开头 let srReg = /^#?(\*|星铁|星轨|穹轨|星穹|崩铁|星穹铁道|崩坏星穹铁道|铁道)+/ - if (srReg.test(msg)) { + let gclink = /\/common\//.test(msg) + if (srReg.test(msg) || gclink) { console.log('sr test true') e.isSr = true msg = msg.replace(srReg, '#星铁') diff --git a/plugins/genshin/model/gachaLog.js b/plugins/genshin/model/gachaLog.js index 77fa0b7..c64e4a6 100644 --- a/plugins/genshin/model/gachaLog.js +++ b/plugins/genshin/model/gachaLog.js @@ -55,7 +55,7 @@ export default class GachaLog extends base { if (i <= 1) await common.sleep(500) } - await this.e.reply(`抽卡记录更新完成,您还可回复\n【#${this?.e?.isSr?'光锥':'武器'}记录】统计${this?.e?.isSr?'光锥':'武器'}池数据\n【#角色统计】按卡池统计数据\n【#导出记录】导出记录数据`) + await this.e.reply(`抽卡记录更新完成,您还可回复\n【#${this?.e?.isSr?'星铁光锥':'武器'}记录】统计${this?.e?.isSr?'星铁光锥':'武器'}池数据\n【#${this?.e?.isSr?'星铁':''}角色统计】按卡池统计数据\n【#导出记录】导出记录数据`) this.isLogUrl = true From 8cc161a2c41ffefa6e5c86ed012e8c6cc2bbcf74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B0=8F=E9=A3=9E?= <42599406+xfdown@users.noreply.github.com> Date: Sat, 13 May 2023 20:13:35 +0800 Subject: [PATCH 12/33] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E6=9F=A5=E8=AF=A2?= =?UTF-8?q?=E5=8E=9F=E7=A5=9E3.7=E5=89=8D=E7=9E=BB=E5=89=8D=E7=9E=BB?= =?UTF-8?q?=E5=85=91=E6=8D=A2=E7=A0=81=E3=80=82=20(#113)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- plugins/genshin/apps/exchange.js | 78 +++++++++++++++----------------- 1 file changed, 37 insertions(+), 41 deletions(-) diff --git a/plugins/genshin/apps/exchange.js b/plugins/genshin/apps/exchange.js index a3498ae..5698156 100644 --- a/plugins/genshin/apps/exchange.js +++ b/plugins/genshin/apps/exchange.js @@ -5,7 +5,7 @@ import lodash from 'lodash' import MysInfo from '../model/mys/mysInfo.js' export class exchange extends plugin { - constructor (e) { + constructor(e) { super({ name: '兑换码', dsc: '前瞻直播兑换码', @@ -24,7 +24,7 @@ export class exchange extends plugin { }) } - async getCode () { + async getCode() { this.now = parseInt(Date.now() / 1000) let actid = await this.getActId() if (!actid) return @@ -33,47 +33,55 @@ export class exchange extends plugin { /** index info */ let index = await this.getData('index') if (!index || !index.data) return - if(index.data === null){ + if (index.data === null) { return await this.reply(`错误:\n${index.message}`) } - this.mi18n = index.data.mi18n - let mi18n = await this.getData('mi18n') - - if (index.data.remain > 0) { - let version = mi18n['act-title'].match(/\d.\d/g) - return await this.reply(`暂无直播兑换码\n${version}版本前瞻${mi18n['empty-code-text']}`) + let index_data = index.data.live; + let title = index_data['title']; + if (index_data.remain > 0) { + return await this.reply(`暂无直播兑换码\n${title}`) } let code = await this.getData('code') - if (!code) return + if (!code || !code.data?.code_list) return + let codes = []; + + for (let val of code.data.code_list) { + if (val.code){ + let title = (val.title || '').replace(/\<.*?\>/g,'') + codes.push(title + ':' + val.code) + } + } - code = lodash.map(code, 'code') let msg = '' - if (code.length >= 3) { - msg = [`${mi18n['act-title']}-直播兑换码`, `${mi18n['exchange-tips']}`, ...code] + if (codes.length >= 3) { + msg = [`${title}-直播兑换码`, `兑换码存在有效期,请及时兑换哦~`, ...codes] msg = await common.makeForwardMsg(this.e, msg, msg[0]) } else if (this.e.msg.includes('#')) { - msg += code.join('\n') + msg += codes.join('\n') } else { - msg = `${mi18n['act-title']}-直播兑换码\n` - msg += `${mi18n['exchange-tips']}\n\n` - msg += code.join('\n') + msg = `${title}-直播兑换码\n` + msg += codes.join('\n') } await this.reply(msg) } - async getData (type) { + async getData(type) { let url = { - index: `https://api-takumi.mihoyo.com/event/bbslive/index?act_id=${this.actId}`, - mi18n: `https://webstatic.mihoyo.com/admin/mi18n/bbs_cn/${this.mi18n}/${this.mi18n}-zh-cn.json`, - code: `https://webstatic.mihoyo.com/bbslive/code/${this.actId}.json?version=1&time=${this.now}`, + index: `https://api-takumi.mihoyo.com/event/miyolive/index`, + code: `https://api-takumi-static.mihoyo.com/event/miyolive/refreshCode?version=${this.code_ver}&time=${parseInt(new Date().getTime() / 1000)}`, actId: "https://bbs-api.mihoyo.com/painter/api/user_instant/list?offset=0&size=20&uid=75276550", } let response try { - response = await fetch(url[type], { method: 'get' }) + response = await fetch(url[type], { + method: 'get', + headers: { + 'x-rpc-act_id': this.actId + } + }) } catch (error) { logger.error(error.toString()) return false @@ -87,25 +95,13 @@ export class exchange extends plugin { return res } - // async getActId () { - // let ret = await this.getData('actId') - // if (!ret || ret.retcode !== 0) return false - - // let post = lodash.map(ret.data.posts, 'post') - // post = lodash.maxBy(post, 'created_at') - // let actId = post.content.replace(/\[链接\]|\[图片\]/g, '').trim() - // if (!actId) return false - - // return actId - // } - async getActId() { // 获取 "act_id" let ret = await this.getData('actId') if (ret.error || ret.retcode !== 0) { return ""; } - + let actId = ""; let keywords = ["来看《原神》", "版本前瞻特别节目"]; for (const p of ret.data.list) { @@ -119,24 +115,24 @@ export class exchange extends plugin { let shit = JSON.parse(post.structured_content); for (let segment of shit) { if (segment.insert.toString().includes('观看直播') && segment.attributes.link) { - let matched = segment.attributes.link.match(/act_id=(\d{8}ys\d{4})/); + let matched = segment.attributes.link.match(/act_id=(.*?)&/); if (matched) { actId = matched[1]; } } } - + if (actId) { break; } } - + return actId; } - async useCode(){ + async useCode() { let cdkCode = this.e.message[0].text.split(/#(兑换码使用|cdk-u) /, 3)[2]; - let res = await MysInfo.get(this.e, 'useCdk',{cdk:cdkCode}) - if(res){ + let res = await MysInfo.get(this.e, 'useCdk', { cdk: cdkCode }) + if (res) { this.e.reply(`${res.data.msg}`) } } From d208a5758af04a918dba34ace3cb8f76aa58e9be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B0=8F=E9=A3=9E?= <42599406+xfdown@users.noreply.github.com> Date: Sat, 13 May 2023 20:47:29 +0800 Subject: [PATCH 13/33] =?UTF-8?q?=E5=88=A0=E9=99=A4=E5=85=91=E6=8D=A2?= =?UTF-8?q?=E7=A0=81=E6=A0=87=E9=A2=98=E3=80=82=20(#114)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- plugins/genshin/apps/exchange.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/genshin/apps/exchange.js b/plugins/genshin/apps/exchange.js index 5698156..892e518 100644 --- a/plugins/genshin/apps/exchange.js +++ b/plugins/genshin/apps/exchange.js @@ -48,8 +48,8 @@ export class exchange extends plugin { for (let val of code.data.code_list) { if (val.code){ - let title = (val.title || '').replace(/\<.*?\>/g,'') - codes.push(title + ':' + val.code) + //let title = (val.title || '').replace(/\<.*?\>/g,'') + codes.push(val.code) } } From 7266fea29914a74e62c71dc85be42147fdaff051 Mon Sep 17 00:00:00 2001 From: touchscale <11134128+touchscale_admin@user.noreply.gitee.com> Date: Sun, 14 May 2023 21:20:35 +0000 Subject: [PATCH 14/33] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E7=99=BB=E5=BD=95?= =?UTF-8?q?=E9=AA=8C=E8=AF=81=E7=A0=81=E8=87=AA=E5=8A=A8=E8=8E=B7=E5=8F=96?= =?UTF-8?q?ticket?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: touchscale <11134128+touchscale_admin@user.noreply.gitee.com> --- lib/events/login.js | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/lib/events/login.js b/lib/events/login.js index 8f5bb9f..ce3d9b7 100644 --- a/lib/events/login.js +++ b/lib/events/login.js @@ -73,13 +73,18 @@ export default class loginEvent extends EventListener { type: 'list', name: 'type', message: '触发滑动验证,需要获取ticket通过验证,请选择获取方式:', - choices: ['1.手动获取ticket', '2.滑动验证app请求码获取'] + choices: ['0.自动获取ticket', '1.手动获取ticket', '2.滑动验证app请求码获取'] } ]) await common.sleep(200) let ticket + if (ret.type == '0.自动获取ticket') { + ticket = await this.getTicket(event.url) + if (!ticket) console.log('\n请求错误,返回手动获取ticket方式\n') + } + if (ret.type == '2.滑动验证app请求码获取') { ticket = await this.requestCode(event.url) if (!ticket) console.log('\n请求错误,返回手动获取ticket方式\n') @@ -103,6 +108,27 @@ export default class loginEvent extends EventListener { this.client.submitSlider(ticket.trim()) } + async getTicket (url) { + let req = `https://hlhs-nb.cn/captcha/slider?key=${Bot.uin}` + await fetch(req, { + method: 'POST', + body: JSON.stringify({ url }) + }) + + console.log('\n----请打开下方链接并在2分钟内进行验证----') + console.log(`${logger.green(req)}\n----完成后将自动进行登录----`) + + for (let i = 0; i < 40; i++) { + let res = await fetch(req, { + method: 'POST', + body: JSON.stringify({ submit: Bot.uin }) + }) + res = await res.json() + if (res.data?.ticket) return res.data.ticket + await common.sleep(3000) + } + } + async requestCode (url) { let txhelper = { url: url.replace('ssl.captcha.qq.com', 'txhelper.glitch.me') From 87c29e8795f8499704aa75ca76c4f89f261b79c9 Mon Sep 17 00:00:00 2001 From: Rrrrrrray <28804884+Rrrrrrray@users.noreply.github.com> Date: Wed, 17 May 2023 05:27:59 +0800 Subject: [PATCH 15/33] =?UTF-8?q?update=EF=BC=9A=E6=98=9F=E9=93=81?= =?UTF-8?q?=E4=B8=8B=E5=8D=8A=E5=8D=A1=E6=B1=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- plugins/genshin/defSet/pool/11.yaml | 9 +++++++++ plugins/genshin/defSet/pool/12.yaml | 9 +++++++++ 2 files changed, 18 insertions(+) diff --git a/plugins/genshin/defSet/pool/11.yaml b/plugins/genshin/defSet/pool/11.yaml index f32a0ec..29bea3b 100644 --- a/plugins/genshin/defSet/pool/11.yaml +++ b/plugins/genshin/defSet/pool/11.yaml @@ -1,3 +1,12 @@ +- from: '2023-05-17 18:00:00' + to: '2023-06-06 14:59:59' + five: + - 景元 + four: + - 停云 + - 素裳 + - 三月七 + name: 天戈麾斥 - from: '2023-04-26 08:00:00' to: '2023-05-17 16:00:00' five: diff --git a/plugins/genshin/defSet/pool/12.yaml b/plugins/genshin/defSet/pool/12.yaml index be15d93..c70d8bd 100644 --- a/plugins/genshin/defSet/pool/12.yaml +++ b/plugins/genshin/defSet/pool/12.yaml @@ -1,3 +1,12 @@ +- from: '2023-05-17 18:00:00' + to: '2023-06-06 14:59:59' + five: + - 拂晓之前 + four: + - 与行星相会 + - 唯有沉默 + - 余生的第一天 + name: 流光定影 - from: '2023-04-26 08:00:00' to: '2023-05-17 16:00:00' five: From 1f08cca1ba397647d53b2d131593a3b7b7f87790 Mon Sep 17 00:00:00 2001 From: touchscale <11134128+touchscale_admin@user.noreply.gitee.com> Date: Tue, 16 May 2023 23:32:40 +0000 Subject: [PATCH 16/33] update package.json. Signed-off-by: touchscale <11134128+touchscale_admin@user.noreply.gitee.com> --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1ea1feb..cbf3444 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,7 @@ "node-xlsx": "^0.21.2", "oicq": "^2.3.1", "pm2": "^5.3.0", - "puppeteer": "^20.1.2", + "puppeteer": "^20.2.1", "redis": "^4.6.6", "sequelize": "^6.31.1", "sqlite3": "^5.1.6", From 41bdaf5b55e339976ef9e84462c9a6bcdb645e1f Mon Sep 17 00:00:00 2001 From: touchscale <11134128+touchscale_admin@user.noreply.gitee.com> Date: Wed, 17 May 2023 09:43:19 +0000 Subject: [PATCH 17/33] =?UTF-8?q?=E4=BF=AE=E5=A4=8D#=E6=98=9F=E9=93=81?= =?UTF-8?q?=E5=85=AC=E5=91=8A/=E8=B5=84=E8=AE=AF/=E6=B4=BB=E5=8A=A8?= =?UTF-8?q?=E6=8A=A5=E9=94=99puppeteer.browserInit=20is=20not=20a=20functi?= =?UTF-8?q?on?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: touchscale <11134128+touchscale_admin@user.noreply.gitee.com> --- plugins/genshin/model/srmysNews.js | 79 ++---------------------------- 1 file changed, 3 insertions(+), 76 deletions(-) diff --git a/plugins/genshin/model/srmysNews.js b/plugins/genshin/model/srmysNews.js index 934e91b..8027f4c 100644 --- a/plugins/genshin/model/srmysNews.js +++ b/plugins/genshin/model/srmysNews.js @@ -44,86 +44,13 @@ export default class MysNews extends base { const param = await this.newsDetail(postId) - const img = await this.rander(param) + const img = await this.render(param) return await this.replyMsg(img, `崩坏星穹铁道${typeName}:${param.data.post.subject}`) } - async rander (param) { - const pageHeight = 7000 - - await puppeteer.browserInit() - - if (!puppeteer.browser) return false - - const savePath = puppeteer.dealTpl('mysNews', param) - if (!savePath) return false - - const page = await puppeteer.browser.newPage() - try { - await page.goto(`file://${_path}${lodash.trim(savePath, '.')}`, { timeout: 120000 }) - const body = await page.$('#container') || await page.$('body') - const boundingBox = await body.boundingBox() - - const num = Math.round(boundingBox.height / pageHeight) || 1 - - if (num > 1) { - await page.setViewport({ - width: boundingBox.width, - height: pageHeight + 100 - }) - } - - const img = [] - for (let i = 1; i <= num; i++) { - const randData = { - type: 'jpeg', - quality: 90 - } - - if (i != 1 && i == num) { - await page.setViewport({ - width: boundingBox.width, - height: parseInt(boundingBox.height) - pageHeight * (num - 1) - }) - } - - if (i != 1 && i <= num) { - await page.evaluate(() => window.scrollBy(0, 7000)) - } - - let buff - if (num == 1) { - buff = await body.screenshot(randData) - } else { - buff = await page.screenshot(randData) - } - - if (num > 2) await common.sleep(200) - - puppeteer.renderNum++ - /** 计算图片大小 */ - const kb = (buff.length / 1024).toFixed(2) + 'kb' - - logger.mark(`[图片生成][${this.model}][${puppeteer.renderNum}次] ${kb}`) - - img.push(segment.image(buff)) - } - - await page.close().catch((err) => logger.error(err)) - - if (num > 1) { - logger.mark(`[图片生成][${this.model}] 处理完成`) - } - return img - } catch (error) { - logger.error(`图片生成失败:${this.model}:${error}`) - /** 关闭浏览器 */ - if (puppeteer.browser) { - await puppeteer.browser.close().catch((err) => logger.error(err)) - } - puppeteer.browser = false - } + async render (param) { + return await puppeteer.screenshots(this.model, param) } async newsDetail (postId) { From 5641775a2057db482931ca078a1b70ca5ffac8c1 Mon Sep 17 00:00:00 2001 From: touchscale <11134128+touchscale_admin@user.noreply.gitee.com> Date: Wed, 17 May 2023 13:47:32 +0000 Subject: [PATCH 18/33] update plugins/genshin/model/srmysNews.js. Signed-off-by: touchscale <11134128+touchscale_admin@user.noreply.gitee.com> --- plugins/genshin/model/srmysNews.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/genshin/model/srmysNews.js b/plugins/genshin/model/srmysNews.js index 8027f4c..68a95a4 100644 --- a/plugins/genshin/model/srmysNews.js +++ b/plugins/genshin/model/srmysNews.js @@ -251,7 +251,7 @@ export default class MysNews extends base { logger.mark(`[崩坏星穹铁道${typeName}推送] ${param.data.post.subject}`) this[postId] = { - img: await this.rander(param), + img: await this.render(param), title: param.data.post.subject } } From 9d53d3dcf041c203cb1de4df42ebbe27bf9dec6c Mon Sep 17 00:00:00 2001 From: touchscale <11134128+touchscale_admin@user.noreply.gitee.com> Date: Fri, 19 May 2023 06:13:06 +0000 Subject: [PATCH 19/33] update package.json. Signed-off-by: touchscale <11134128+touchscale_admin@user.noreply.gitee.com> --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index cbf3444..a99ea35 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,7 @@ "chalk": "^5.2.0", "chokidar": "^3.5.3", "https-proxy-agent": "5.0.1", - "icqq": "^0.3.10", + "icqq": "^0.3.12", "image-size": "^1.0.2", "inquirer": "^8.2.5", "lodash": "^4.17.21", From 3f2dc44a15c1cc0733b552e2a10e8568e5c66cd2 Mon Sep 17 00:00:00 2001 From: touchscale <11134128+touchscale_admin@user.noreply.gitee.com> Date: Fri, 19 May 2023 16:58:05 +0000 Subject: [PATCH 20/33] update package.json. Signed-off-by: touchscale <11134128+touchscale_admin@user.noreply.gitee.com> --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a99ea35..64181e6 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,7 @@ "chalk": "^5.2.0", "chokidar": "^3.5.3", "https-proxy-agent": "5.0.1", - "icqq": "^0.3.12", + "icqq": "^0.3.13", "image-size": "^1.0.2", "inquirer": "^8.2.5", "lodash": "^4.17.21", From 93f65fb6c2aaef852448178a2b34c136b14b008e Mon Sep 17 00:00:00 2001 From: touchscale <11134128+touchscale_admin@user.noreply.gitee.com> Date: Sat, 20 May 2023 14:01:33 +0000 Subject: [PATCH 21/33] update package.json. Signed-off-by: touchscale <11134128+touchscale_admin@user.noreply.gitee.com> --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 64181e6..6914263 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,7 @@ "chalk": "^5.2.0", "chokidar": "^3.5.3", "https-proxy-agent": "5.0.1", - "icqq": "^0.3.13", + "icqq": "^0.3.14", "image-size": "^1.0.2", "inquirer": "^8.2.5", "lodash": "^4.17.21", From ef2f7c098942046a043c56c154011e4892ebda6f Mon Sep 17 00:00:00 2001 From: touchscale <11134128+touchscale_admin@user.noreply.gitee.com> Date: Sat, 20 May 2023 14:10:49 +0000 Subject: [PATCH 22/33] update package.json. Signed-off-by: touchscale <11134128+touchscale_admin@user.noreply.gitee.com> --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 6914263..27ccf89 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,7 @@ "yaml": "^2.2.2" }, "devDependencies": { - "eslint": "^8.40.0", + "eslint": "^8.41.0", "eslint-config-standard": "^17.0.0", "eslint-plugin-import": "^2.27.5", "eslint-plugin-n": "^15.7.0", From 400009bf44dea8a01ab9c5a1c1c565eafb28e5f3 Mon Sep 17 00:00:00 2001 From: Elsie Weber Date: Mon, 22 May 2023 11:39:33 +0800 Subject: [PATCH 23/33] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E9=BB=91=E7=99=BD?= =?UTF-8?q?=E5=90=8D=E5=8D=95=E4=B8=8D=E7=94=9F=E6=95=88bug=20(#120)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/config/config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/config/config.js b/lib/config/config.js index 0f0a64a..1f43cbc 100644 --- a/lib/config/config.js +++ b/lib/config/config.js @@ -104,7 +104,7 @@ class Cfg { } /** notice配置 */ - getOther () { + getNotice () { let def = this.getdefSet('notice') let config = this.getConfig('notice') return { ...def, ...config } From a88d205eb39d5f148eca338ab643c6b796511800 Mon Sep 17 00:00:00 2001 From: sameu Date: Mon, 22 May 2023 11:40:18 +0800 Subject: [PATCH 24/33] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=BC=BA=E5=88=B6?= =?UTF-8?q?=E6=9B=B4=E6=96=B0=E7=9A=84=E6=96=B9=E6=B3=95=20(#123)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- plugins/other/update.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/other/update.js b/plugins/other/update.js index d27572a..c08794f 100644 --- a/plugins/other/update.js +++ b/plugins/other/update.js @@ -104,7 +104,7 @@ export class update extends plugin { let type = '更新' if (this.e.msg.includes('强制')) { type = '强制更新' - cm = `git reset --hard origin/master && ${cm}` + cm = `git fetch --all && git reset --hard && ${cm}` } if (plugin) { From 1233964e78c736e7528763d002a189fc26a78dd4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B0=8F=E9=A3=9E?= <42599406+xfdown@users.noreply.github.com> Date: Mon, 22 May 2023 11:41:15 +0800 Subject: [PATCH 25/33] =?UTF-8?q?icqq=E7=89=88=E6=9C=AC=E5=8D=87=E7=BA=A7?= =?UTF-8?q?=E8=87=B30.3.14=EF=BC=8C=E4=BF=AE=E5=A4=8D=E6=A0=87=E9=A2=98?= =?UTF-8?q?=E8=A2=AB=E8=A6=86=E7=9B=96=E9=97=AE=E9=A2=98=EF=BC=8Cold=5Fand?= =?UTF-8?q?roid=E6=94=B9=E4=B8=BA=E5=AE=89=E5=8D=938.8.88=EF=BC=8C?= =?UTF-8?q?=E5=85=91=E6=8D=A2=E7=A0=81api=E8=B5=8B=E5=80=BCcode=5Fver?= =?UTF-8?q?=E3=80=82=20(#126)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/default_config/qq.yaml | 4 ++-- lib/config/init.js | 10 +++++----- lib/config/qq.js | 4 ++-- plugins/genshin/apps/exchange.js | 5 ++++- 4 files changed, 13 insertions(+), 10 deletions(-) diff --git a/config/default_config/qq.yaml b/config/default_config/qq.yaml index 6745bac..2407f95 100644 --- a/config/default_config/qq.yaml +++ b/config/default_config/qq.yaml @@ -2,5 +2,5 @@ qq: # 密码,为空则用扫码登录,扫码登录现在仅能在同一ip下进行 pwd: -# 1:安卓手机、 2:aPad 、 3:安卓手表、 4:MacOS 、 5:iPad 、 6:old_Android -platform: 5 \ No newline at end of file +# 1:安卓手机、 2:aPad 、 3:安卓手表、 4:MacOS 、 5:iPad 、 6:安卓8.8.88 +platform: 6 \ No newline at end of file diff --git a/lib/config/init.js b/lib/config/init.js index 64fbf05..6bfeb5d 100644 --- a/lib/config/init.js +++ b/lib/config/init.js @@ -31,7 +31,7 @@ async function UpdateTitle() { title += ' iPad' break case 6: - title += ' old_Android' + title += ' 安卓8.8.88' break default: } @@ -73,9 +73,6 @@ async function checkInit () { /** 检查qq.yaml */ await createQQ() - //** 更新标题 */ - await UpdateTitle() - /** 日志设置 */ setLog() @@ -83,5 +80,8 @@ async function checkInit () { await redisInit() - checkRun() + await checkRun() + + //** 更新标题 */ + await UpdateTitle() } diff --git a/lib/config/qq.js b/lib/config/qq.js index 36fa306..d6b99cd 100644 --- a/lib/config/qq.js +++ b/lib/config/qq.js @@ -33,10 +33,10 @@ export default async function createQQ () { message: '请选择登录端口:', name: 'platform', default: '6', - choices: ['old_Android', 'iPad', '安卓手机', '安卓手表', 'MacOS', 'aPad'], + choices: ['安卓8.8.88', 'iPad', '安卓手机', '安卓手表', 'MacOS', 'aPad'], filter: (val) => { switch (val) { - case 'old_Android':return 6 + case '安卓8.8.88':return 6 case 'iPad':return 5 case 'MacOS':return 4 case '安卓手机':return 1 diff --git a/plugins/genshin/apps/exchange.js b/plugins/genshin/apps/exchange.js index 892e518..d45807c 100644 --- a/plugins/genshin/apps/exchange.js +++ b/plugins/genshin/apps/exchange.js @@ -25,6 +25,7 @@ export class exchange extends plugin { } async getCode() { + this.code_ver = '' this.now = parseInt(Date.now() / 1000) let actid = await this.getActId() if (!actid) return @@ -36,8 +37,10 @@ export class exchange extends plugin { if (index.data === null) { return await this.reply(`错误:\n${index.message}`) } + let index_data = index.data.live; let title = index_data['title']; + this.code_ver = index_data['code_ver']; if (index_data.remain > 0) { return await this.reply(`暂无直播兑换码\n${title}`) } @@ -70,7 +73,7 @@ export class exchange extends plugin { async getData(type) { let url = { index: `https://api-takumi.mihoyo.com/event/miyolive/index`, - code: `https://api-takumi-static.mihoyo.com/event/miyolive/refreshCode?version=${this.code_ver}&time=${parseInt(new Date().getTime() / 1000)}`, + code: `https://api-takumi-static.mihoyo.com/event/miyolive/refreshCode?version=${this.code_ver}&time=${this.now}`, actId: "https://bbs-api.mihoyo.com/painter/api/user_instant/list?offset=0&size=20&uid=75276550", } From 8488cbc7f225bbcddc13a2dac8185c5e1cd6efbf Mon Sep 17 00:00:00 2001 From: Kokomi <102026640+yoimiya-kokomi@users.noreply.github.com> Date: Sun, 28 May 2023 04:47:42 +0800 Subject: [PATCH 26/33] merge dev (#143) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 初步支持星铁CK绑定及多UID切换 * 重构CK与UID管理逻辑 * 修正user初始化时ltuid记录错误的问题 * 调整用户uid存储的数据库结构 * 修正无CK用户绑定UID无效的问题 * 删除ck、我的ck命令支持 * 在旧数据迁移时备份ck文件 * 修正uid切换无效的问题 * update plugins/genshin/defSet/pool/301.yaml. Signed-off-by: touchscale <11134128+touchscale_admin@user.noreply.gitee.com> * update plugins/genshin/defSet/pool/302.yaml. Signed-off-by: touchscale <11134128+touchscale_admin@user.noreply.gitee.com> * 增加#删除uid 功能,初步修正uid记录的一些问题 --------- Signed-off-by: touchscale <11134128+touchscale_admin@user.noreply.gitee.com> Co-authored-by: touchscale <11134128+touchscale_admin@user.noreply.gitee.com> Co-authored-by: Kokomi <4964418+yoimiya-kokomi@user.noreply.gitee.com> --- CHANGELOG.md | 6 + lib/plugins/loader.js | 1 - plugins/genshin/apps/user.js | 20 +- plugins/genshin/defSet/pool/301.yaml | 10 + plugins/genshin/defSet/pool/302.yaml | 12 + plugins/genshin/model/blueprint.js | 2 +- plugins/genshin/model/calculator.js | 2 +- plugins/genshin/model/db/BaseModel.js | 26 ++ plugins/genshin/model/db/MysUserDB.js | 68 ++++ plugins/genshin/model/db/UserDB.js | 85 +++++ plugins/genshin/model/db/UserGameDB.js | 43 +++ plugins/genshin/model/db/index.js | 24 ++ plugins/genshin/model/mys/BaseModel.js | 34 +- plugins/genshin/model/mys/DailyCache.js | 121 +++--- plugins/genshin/model/mys/MysUser.js | 483 ++++++++++++------------ plugins/genshin/model/mys/MysUtil.js | 49 +++ plugins/genshin/model/mys/NoteUser.js | 439 ++++++++++++--------- plugins/genshin/model/mys/apiTool.js | 264 ++++++------- plugins/genshin/model/mys/mysInfo.js | 190 +++++----- plugins/genshin/model/note.js | 217 +++++------ plugins/genshin/model/roleList.js | 2 +- plugins/genshin/model/today.js | 2 +- plugins/genshin/model/user.js | 362 +++++++++--------- 23 files changed, 1444 insertions(+), 1018 deletions(-) create mode 100644 plugins/genshin/model/db/BaseModel.js create mode 100644 plugins/genshin/model/db/MysUserDB.js create mode 100644 plugins/genshin/model/db/UserDB.js create mode 100644 plugins/genshin/model/db/UserGameDB.js create mode 100644 plugins/genshin/model/db/index.js create mode 100644 plugins/genshin/model/mys/MysUtil.js diff --git a/CHANGELOG.md b/CHANGELOG.md index adb19cb..30c3a71 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +# 3.1.0 Dev + +* !!!暂未完成,会有很多错误,不建议升级!!! +* 重构CK与UID管理逻辑 +* 底层对星铁查询进行支持 + # 3.0.2 * 3.6卡池以及图像武器别名等数据更新 **@cvs** diff --git a/lib/plugins/loader.js b/lib/plugins/loader.js index f8393ab..c620194 100644 --- a/lib/plugins/loader.js +++ b/lib/plugins/loader.js @@ -361,7 +361,6 @@ class PluginsLoader { let srReg = /^#?(\*|星铁|星轨|穹轨|星穹|崩铁|星穹铁道|崩坏星穹铁道|铁道)+/ let gclink = /\/common\//.test(msg) if (srReg.test(msg) || gclink) { - console.log('sr test true') e.isSr = true msg = msg.replace(srReg, '#星铁') } diff --git a/plugins/genshin/apps/user.js b/plugins/genshin/apps/user.js index 13ecf61..8a5e8c8 100644 --- a/plugins/genshin/apps/user.js +++ b/plugins/genshin/apps/user.js @@ -29,7 +29,7 @@ export class user extends plugin { fnc: 'noLogin' }, { - reg: '^#?我的(ck|cookie)$', + reg: '^#?(原神|星铁)?我的(ck|cookie)$', event: 'message', fnc: 'myCk' }, @@ -38,7 +38,11 @@ export class user extends plugin { fnc: 'delCk' }, { - reg: '^#绑定(uid|UID)?[1-9][0-9]{8}$', + reg: '^#?(原神|星铁)?(删除|解绑)uid\\s*[0-9]{1,2}$', + fnc: 'delUid' + }, + { + reg: '^#(原神|星铁)?绑定(uid|UID)?[1-9][0-9]{8}$', fnc: 'bingUid' }, { @@ -146,6 +150,15 @@ export class user extends plugin { } } + async delUid () { + let index = this.e.msg.match(/[0-9]{1,2}$/g) + let uidIdx = index && index[0] + let game = this.e + if (uidIdx) { + await this.User.delUid(uidIdx, game) + } + } + /** 我的ck */ async myCk () { if (this.e.isGroup) { @@ -157,7 +170,8 @@ export class user extends plugin { /** 加载旧的绑定ck json */ loadOldData () { - this.User.loadOldData() + this.User.loadOldDataV2() + this.User.loadOldDataV3() } /** 检查用户CK状态 **/ diff --git a/plugins/genshin/defSet/pool/301.yaml b/plugins/genshin/defSet/pool/301.yaml index 431d262..ce9bcf2 100644 --- a/plugins/genshin/defSet/pool/301.yaml +++ b/plugins/genshin/defSet/pool/301.yaml @@ -1,3 +1,13 @@ +- from: '2023-05-24 06:00:00' + to: '2023-06-13 17:59:59' + five: + - 宵宫 + - 八重神子 + four: + - 绮良良 + - 云堇 + - 重云 + name: 焰色天河|华紫樱绯 - from: '2023-05-02 18:00:00' to: '2023-05-23 14:59:59' five: diff --git a/plugins/genshin/defSet/pool/302.yaml b/plugins/genshin/defSet/pool/302.yaml index 69201a7..e887a40 100644 --- a/plugins/genshin/defSet/pool/302.yaml +++ b/plugins/genshin/defSet/pool/302.yaml @@ -1,3 +1,15 @@ +- from: '2023-05-24 06:00:00' + to: '2023-06-13 17:59:59' + five: + - 飞雷之弦振 + - 神乐之真意 + four: + - 恶王丸 + - 笛剑 + - 匣里灭辰 + - 流浪乐章 + - 弓藏 + name: 神铸赋形 - from: '2023-05-02 18:00:00' to: '2023-05-23 14:59:59' five: diff --git a/plugins/genshin/model/blueprint.js b/plugins/genshin/model/blueprint.js index 4d24c62..a8d1a27 100644 --- a/plugins/genshin/model/blueprint.js +++ b/plugins/genshin/model/blueprint.js @@ -14,7 +14,7 @@ export default class blueprint extends base { let uid = await MysInfo.getUid(this.e, false) if (!uid) return false /** 判断是否绑定了ck */ - let ck = await MysInfo.checkUidBing(uid) + let ck = await MysInfo.checkUidBing(uid, this.e) if (!ck) { await this.e.reply(MysInfo.tips) return false diff --git a/plugins/genshin/model/calculator.js b/plugins/genshin/model/calculator.js index 07736d1..ea5a1dc 100644 --- a/plugins/genshin/model/calculator.js +++ b/plugins/genshin/model/calculator.js @@ -18,7 +18,7 @@ export default class Calculator extends base { if (!uid) return false /** 判断是否绑定了ck */ - let ck = await MysInfo.checkUidBing(uid) + let ck = await MysInfo.checkUidBing(uid, this.e) if (!ck) { await this.e.reply(MysInfo.tips) return false diff --git a/plugins/genshin/model/db/BaseModel.js b/plugins/genshin/model/db/BaseModel.js new file mode 100644 index 0000000..45863cb --- /dev/null +++ b/plugins/genshin/model/db/BaseModel.js @@ -0,0 +1,26 @@ +import { Sequelize, DataTypes, Model } from 'sequelize' +import { Data } from '#miao' + +Data.createDir('/data/db', 'root') +let dbPath = process.cwd() + '/data/db/data.db' + +// TODO DB自定义 +const sequelize = new Sequelize({ + dialect: 'sqlite', + storage: dbPath, + logging: false +}) + +await sequelize.authenticate() + +export default class BaseModel extends Model { + static Types = DataTypes + + static initDB (model, columns) { + let name = model.name + console.log('Model Name', name) + name = name.replace(/DB$/, 's') + model.init(columns, { sequelize, tableName: name }) + model.COLUMNS = columns + } +} diff --git a/plugins/genshin/model/db/MysUserDB.js b/plugins/genshin/model/db/MysUserDB.js new file mode 100644 index 0000000..a5d1f81 --- /dev/null +++ b/plugins/genshin/model/db/MysUserDB.js @@ -0,0 +1,68 @@ +import BaseModel from './BaseModel.js' + +const { Types } = BaseModel + +const COLUMNS = { + // 用户ID,qq为数字 + ltuid: { + type: Types.INTEGER, + primaryKey: true + }, + + // MysUser类型,mys / hoyolab + type: { + type: Types.STRING, + defaultValue: 'mys', + notNull: true + }, + + // CK + ck: Types.STRING, + device: Types.STRING, + uids: { + type: Types.STRING, + get () { + let data = this.getDataValue('uids') + let ret = {} + try { + ret = JSON.parse(data) + } catch (e) { + ret = {} + } + return ret + }, + set (uids) { + this.setDataValue('uids', JSON.stringify(uids)) + } + } +} + +class MysUserDB extends BaseModel { + static async find (ltuid = '', create = false) { + // DB查询 + let mys = await MysUserDB.findByPk(ltuid) + if (!mys && create) { + mys = await MysUserDB.build({ + ltuid + }) + } + return mys || false + } + + async saveDB (mys) { + if (!mys.ck || !mys.device || !mys.db) { + return false + } + let db = this + this.ck = mys.ck + this.type = mys.type + this.device = mys.device + this.uids = mys.uids + await db.save() + } +} + +BaseModel.initDB(MysUserDB, COLUMNS) +await MysUserDB.sync() + +export default MysUserDB diff --git a/plugins/genshin/model/db/UserDB.js b/plugins/genshin/model/db/UserDB.js new file mode 100644 index 0000000..2faf1df --- /dev/null +++ b/plugins/genshin/model/db/UserDB.js @@ -0,0 +1,85 @@ +import BaseModel from './BaseModel.js' +import lodash from 'lodash' +import { UserGameDB } from './index.js' +import MysUtil from '../mys/MysUtil.js' + +const { Types } = BaseModel + +const COLUMNS = { + // 用户ID,qq为数字 + id: { + type: Types.STRING, + autoIncrement: false, + primaryKey: true + }, + + type: { + type: Types.STRING, + defaultValue: 'qq', + notNull: true + }, + + // 昵称 + name: Types.STRING, + + // 头像 + face: Types.STRING, + + ltuids: Types.STRING +} + +class UserDB extends BaseModel { + static async find (id, type = 'qq') { + // user_id + id = type === 'qq' ? '' + id : type + id + // DB查询 + let user = await UserDB.findByPk(id, { + include: { + model: UserGameDB, + as: 'games' + } + }) + if (!user) { + user = await UserDB.build({ + id, + type + }) + } + return user + } + + async saveDB (user) { + let db = this + let ltuids = [] + lodash.forEach(user.mysUsers, (mys) => { + if (mys.ck && mys.ltuid) { + ltuids.push(mys.ltuid) + } + }) + db.ltuids = ltuids.join(',') + let games = [] + await MysUtil.eachGame(async (key) => { + let game = user.games[key] + if (!game && (user.mainUid[key] || !lodash.isEmpty(user.uidMap[key]))) { + game = await db.createGame({ + game: key + }) + } + if (game) { + game.uid = user.mainUid[key] + game.data = user.uidMap[key] + games.push(game) + await game.save() + } + }) + if (games.length > 0) { + await this.setGames(games) + } + await this.save() + } +} + +BaseModel.initDB(UserDB, COLUMNS) +await UserDB.sync() + +export default UserDB \ No newline at end of file diff --git a/plugins/genshin/model/db/UserGameDB.js b/plugins/genshin/model/db/UserGameDB.js new file mode 100644 index 0000000..c29797b --- /dev/null +++ b/plugins/genshin/model/db/UserGameDB.js @@ -0,0 +1,43 @@ +import BaseModel from './BaseModel.js' +import lodash from 'lodash' + +const { Types } = BaseModel + +const COLUMNS = { + // 用户ID,qq为数字 + userId: { + type: Types.STRING + }, + game: Types.STRING, + uid: Types.STRING, + data: { + type: Types.STRING, + get () { + let data = this.getDataValue('data') + let ret = {} + try { + data = JSON.parse(data) + } catch (e) { + data = [] + } + lodash.forEach(data, (ds) => { + if (ds.uid) { + ret[ds.uid] = ds + } + }) + return ret + }, + set (data) { + this.setDataValue('data', JSON.stringify(lodash.values(data))) + } + } +} + +class UserGameDB extends BaseModel { + +} + +BaseModel.initDB(UserGameDB, COLUMNS) +await UserGameDB.sync() + +export default UserGameDB \ No newline at end of file diff --git a/plugins/genshin/model/db/index.js b/plugins/genshin/model/db/index.js new file mode 100644 index 0000000..22cd3e9 --- /dev/null +++ b/plugins/genshin/model/db/index.js @@ -0,0 +1,24 @@ +import UserDB from './UserDB.js' +import MysUserDB from './MysUserDB.js' +import UserGameDB from './UserGameDB.js' + + +UserDB.belongsToMany(MysUserDB, { + through: 'UserLtuids' +}) +MysUserDB.belongsToMany(UserDB, { + through: 'UserLtuids' +}) + +UserDB.hasMany(UserGameDB, { + onDelete: 'RESTRICT', + onUpdate: 'RESTRICT', + foreignKey: 'userId', + as: 'games' +}) +UserGameDB.belongsTo(UserDB, { + foreignKey: 'userId', + as: 'games' +}) + +export { UserDB, MysUserDB, UserGameDB } \ No newline at end of file diff --git a/plugins/genshin/model/mys/BaseModel.js b/plugins/genshin/model/mys/BaseModel.js index 23ae515..baa7433 100644 --- a/plugins/genshin/model/mys/BaseModel.js +++ b/plugins/genshin/model/mys/BaseModel.js @@ -1,6 +1,8 @@ /** * 基础类,提供实例缓存等一些基础方法 */ +import MysUtil from './MysUtil.js' + let cacheMap = {} let reFn = {} @@ -12,19 +14,20 @@ export default class BaseModel { // 获取缓存 _getThis (model, id = '', time = 10 * 60) { const uuid = `${model}:${id}` + this._uuid = uuid if (uuid && cacheMap[uuid]) { return cacheMap[uuid]._expire(time) } - this._uuid = uuid } // 设置缓存 - _cacheThis (time = 10 * 60) { - let id = this._uuid - if (id) { + _cacheThis (model, id, time = 10 * 60) { + const uuid = this._uuid || `${model}:${id}` + this._uuid = uuid + if (uuid) { this._expire(time) - cacheMap[id] = this - return cacheMap[id] + cacheMap[uuid] = this + return cacheMap[uuid] } return this } @@ -44,4 +47,23 @@ export default class BaseModel { return cacheMap[id] } } + + _delCache () { + let id = this._uuid + reFn[id] && clearTimeout(reFn[id]) + delete reFn[id] + delete cacheMap[id] + } + + gameKey (game = 'gs') { + return MysUtil.getGameKey(game) + } + + isGs (game = 'gs') { + return this.gameKey(game) === 'gs' + } + + isSr (game = 'gs') { + return this.gameKey(game) === 'sr' + } } diff --git a/plugins/genshin/model/mys/DailyCache.js b/plugins/genshin/model/mys/DailyCache.js index b4b2d5f..1d08564 100644 --- a/plugins/genshin/model/mys/DailyCache.js +++ b/plugins/genshin/model/mys/DailyCache.js @@ -1,15 +1,16 @@ import moment from 'moment' import BaseModel from './BaseModel.js' +import MysUtil from './MysUtil.js' const servs = ['mys', 'hoyolab'] // 超时时间不必精确,直接定24小时即可 const EX = 3600 * 24 -const redisKeyRoot = 'Yz:genshin:mys:' +const redisKeyRoot = 'Yz:cache:' export default class DailyCache extends BaseModel { - constructor (uid) { + constructor (uid, game = 'config') { super() - const storeKey = DailyCache.getStoreKey(uid) + const storeKey = DailyCache.getStoreKey(uid, game) // 检查实例缓存 let self = this._getThis('store', storeKey) if (self) { @@ -22,40 +23,28 @@ export default class DailyCache extends BaseModel { /** * 传入UID或server标示,返回当日存储对象 * @param uid + * @param game * * 为空则返回与serv无关的dailyCache * * 传入UID,会返回UID对应serv的cache对象 * * 传入servKey (mys/hoyolab),会返回指定的servCache * @returns {DailyCache} */ - static create (uid) { - return new DailyCache(uid) - } - - /** ---- 基础方法 ---- **/ - // 内部方法:获取redis表key键值 - getTableKey (key, sub = '') { - if (sub) { - return `${this.keyPre}:${key}-${sub}` - } else { - return `${this.keyPre}:${key}` - } - } - - // 内部方法:获取server key - static getServKey (uid) { - // 不传入uid为默认cache - if (!uid || uid === 'cache') { - return 'cache' - } - // 传入uid或sever key,判断是mys还是hoyolab - return /^[6-9]|^hoyo|^os/i.test(uid) ? servs[1] : servs[0] + static create (uid, game = 'config') { + return new DailyCache(uid, game) } // 内部方法:获取redis表前缀 - static getStoreKey (uid) { - const serv = DailyCache.getServKey(uid) + static getStoreKey (uid, game = 'config') { + let key + if (!uid || game === 'config') { + key = 'sys:config' + } else { + game = MysUtil.getGameKey(game) + let serv = /^[6-9]|^hoyo|^os/i.test(uid) ? servs[1] : servs[0] + key = `${game}:${serv}` + } const date = moment().format('MM-DD') - return `${serv}-${date}` + return `${key}-${date}` } /** @@ -78,8 +67,8 @@ export default class DailyCache extends BaseModel { static async clearOutdatedData () { let keys = await redis.keys(`${redisKeyRoot}*`) const date = moment().format('MM-DD') - const testReg = new RegExp(`^${redisKeyRoot}(mys|hoyo|hoyolab|cache)-\\d{2}-\\d{2}`) - const todayReg = new RegExp(`^${redisKeyRoot}(mys|hoyo|hoyolab|cache)-${date}`) + const testReg = new RegExp(`^${redisKeyRoot}(mys|hoyolab|config)-\\d{2}-\\d{2}`) + const todayReg = new RegExp(`^${redisKeyRoot}(mys|hoyolab|config)-${date}`) for (let key of keys) { if (testReg.test(key) && !todayReg.test(key)) { await redis.del(key) @@ -87,6 +76,47 @@ export default class DailyCache extends BaseModel { } } + // 内部方法,用于decode value + static decodeValue (value, decode = false) { + if (value && decode) { + try { + return JSON.parse(value) + } catch (e) { + return false + } + } + return value + } + + // 内部方法,用于encode value + static encodeValue (value) { + if (typeof (value) === 'object') { + return JSON.stringify(value) || '' + } + if (typeof (value) === 'undefined') { + return '' + } + return '' + value + } + + /** ---- 基础方法 ---- **/ + // 内部方法:获取redis表key键值 + getTableKey (key, sub = '') { + if (sub) { + return `${this.keyPre}:${key}-${sub}` + } else { + return `${this.keyPre}:${key}` + } + } + + /** + * 【基础数据结构】:Key-Value + * + * 每个key对应一个Value + * 使用redis kv存储,所有操作需要指定表名 + * + * **/ + /** * 设置指定表的过期时间 * @param table 表 @@ -110,14 +140,6 @@ export default class DailyCache extends BaseModel { await redis.del(this.getTableKey(table, 'count')) } - /** - * 【基础数据结构】:Key-Value - * - * 每个key对应一个Value - * 使用redis kv存储,所有操作需要指定表名 - * - * **/ - /** * 获取表指定key内容 * @param table 表名 @@ -176,29 +198,6 @@ export default class DailyCache extends BaseModel { return await redis.set(this.getTableKey(table), value, { EX }) } - // 内部方法,用于decode value - static decodeValue (value, decode = false) { - if (value && decode) { - try { - return JSON.parse(value) - } catch (e) { - return false - } - } - return value - } - - // 内部方法,用于encode value - static encodeValue (value) { - if (typeof (value) === 'object') { - return JSON.stringify(value) || '' - } - if (typeof (value) === 'undefined') { - return '' - } - return '' + value - } - /** * 【基础数据结构】:Key-List * diff --git a/plugins/genshin/model/mys/MysUser.js b/plugins/genshin/model/mys/MysUser.js index 8b4abd1..39c8aae 100644 --- a/plugins/genshin/model/mys/MysUser.js +++ b/plugins/genshin/model/mys/MysUser.js @@ -9,8 +9,11 @@ import DailyCache from './DailyCache.js' import BaseModel from './BaseModel.js' import NoteUser from './NoteUser.js' import MysApi from './mysApi.js' +import MysUtil from './MysUtil.js' import lodash from 'lodash' import fetch from 'node-fetch' +import { MysUserDB, UserDB } from '../db/index.js' +import { Data } from '../../../miao-plugin/components/index.js' const tables = { // ltuid-uid 查询表 @@ -36,9 +39,9 @@ const tables = { } export default class MysUser extends BaseModel { - constructor (data) { + + constructor (ltuid) { super() - let ltuid = data.ltuid if (!ltuid) { return false } @@ -47,66 +50,33 @@ export default class MysUser extends BaseModel { if (!self) { self = this } - // 单日有效缓存,不区分服务器 - self.cache = self.cache || DailyCache.create() - self.uids = self.uids || [] - self.ltuid = data.ltuid - self.ck = self.ck || data.ck - self.qq = self.qq || data.qq || 'pub' - if (data.uid || data.uids) { - self.addUid(data.uid || data.uids) - } - if (data.ck && data.ltuid) { - self.ckData = data - } - // 单日有效缓存,使用uid区分不同服务器 - self.servCache = self.servCache || DailyCache.create(self.uids[0] || 'mys') + this.ltuid = ltuid return self._cacheThis() } // 可传入ltuid、cookie、ck对象来创建MysUser实例 // 在仅传入ltuid时,必须是之前传入过的才能被识别 - static async create (data) { - if (!data) { + static async create (ltuid, db = false) { + ltuid = MysUtil.getLtuid(ltuid) + if (!ltuid) { return false } - if (lodash.isPlainObject(data)) { - return new MysUser(data) - } - // 传入cookie - let testRet = /ltuid=(\d{4,9})/g.exec(data) - if (testRet && testRet[1]) { - let ltuid = testRet[1] - // 尝试使用ltuid创建 - let ckUser = await MysUser.create(ltuid) - if (ckUser) { - return ckUser - } - let uids = await MysUser.getCkUid(data) - if (uids) { - return new MysUser({ - ltuid, - ck: data, - type: 'ck', - uids - }) - } - } - // 传入ltuid - if (/^\d{4,9}$/.test(data)) { - // 查找ck记录 - let cache = DailyCache.create() - let ckData = await cache.kGet(tables.ck, data, true) - if (ckData && ckData.ltuid) { - return new MysUser(ckData) - } - } - return false + let mys = new MysUser(ltuid) + await mys.initDB(db) + return mys + } + + static async forEach (fn) { + let dbs = await MysUserDB.findAll() + await Data.forEach(dbs, async (db) => { + let mys = await MysUser.create(db.ltuid, db) + return await fn(mys) + }) } // 根据uid获取查询MysUser - static async getByQueryUid (uid, onlySelfCk = false) { - let servCache = DailyCache.create(uid) + static async getByQueryUid (uid, game = 'gs', onlySelfCk = false) { + let servCache = DailyCache.create(uid, game) // 查找已经查询过的ltuid || 分配最少查询的ltuid // 根据ltuid获取mysUser 封装 @@ -120,7 +90,7 @@ export default class MysUser extends BaseModel { } // 若声明只获取自己ck,则判断uid是否为本人所有 - if (onlySelfCk && !await ckUser.ownUid(uid)) { + if (onlySelfCk && !ckUser.ownUid(uid, game)) { return false } @@ -148,11 +118,12 @@ export default class MysUser extends BaseModel { } static async eachServ (fn) { - let servs = ['mys', 'hoyolab'] - for (let serv of servs) { - let servCache = DailyCache.create(serv) - await fn(servCache, serv) - } + await MysUtil.eachServ(async (serv) => { + await MysUtil.eachGame(async (game) => { + let servCache = DailyCache.create(serv, game) + await fn(servCache, serv, game) + }) + }) } // 清除当日缓存 @@ -223,106 +194,6 @@ export default class MysUser extends BaseModel { return count } - static async getGameRole (ck, serv = 'mys') { - let url = { - mys: 'https://api-takumi.mihoyo.com/binding/api/getUserGameRolesByCookie', - hoyolab: 'https://api-os-takumi.mihoyo.com/binding/api/getUserGameRolesByCookie?game_biz=hk4e_global' - } - - let res = await fetch(url[serv], { method: 'get', headers: { Cookie: ck } }) - if (!res.ok) return false - res = await res.json() - - return res - } - - // 获取米游社通行证id - static async getUserFullInfo (ck, serv = 'mys') { - let url = { - mys: 'https://bbs-api.mihoyo.com/user/wapi/getUserFullInfo?gids=2', - hoyolab: '' - } - let res = await fetch(url[serv], { - method: 'get', - headers: { - Cookie: ck, - Accept: 'application/json, text/plain, */*', - Connection: 'keep-alive', - Host: 'bbs-api.mihoyo.com', - Origin: 'https://m.bbs.mihoyo.com', - Referer: ' https://m.bbs.mihoyo.com/' - } - }) - if (!res.ok) return res - res = await res.json() - - return res - } - - /** - * 获取ck对应uid列表 - * @param ck 需要获取的ck - * @param withMsg false:uids / true: {uids, msg} - * @param force 忽略缓存,强制更新 - * @returns {Promise<{msg: *, uids}>} - */ - static async getCkUid (ck, withMsg = false, force = false) { - let ltuid = '' - let testRet = /ltuid=(\w{0,9})/g.exec(ck) - if (testRet && testRet[1]) { - ltuid = testRet[1] - } - let uids = [] - let ret = (msg, retUid) => { - retUid = lodash.map(retUid, (a) => a + '') - return withMsg ? { msg, uids: retUid } : retUid - } - if (!ltuid) { - return ret('无ltuid', false) - } - - if (!force) { - // 此处不使用DailyCache,做长期存储 - uids = await redis.get(`Yz:genshin:mys:ltuid-uids:${ltuid}`) - if (uids) { - uids = DailyCache.decodeValue(uids, true) - if (uids && uids.length > 0) { - return ret('', uids) - } - } - } - - uids = [] - let res = null - let msg = 'error' - for (let serv of ['mys', 'hoyolab']) { - let roleRes = await MysUser.getGameRole(ck, serv) - if (roleRes?.retcode === 0) { - res = roleRes - break - } - if (roleRes.retcode * 1 === -100) { - msg = '该ck已失效,请重新登录获取' - } - msg = roleRes.message || 'error' - } - if (!res) return ret(msg, false) - if (!res.data.list || res.data.list.length <= 0) { - return ret('该账号尚未绑定原神或星穹角色', false) - } - - for (let val of res.data.list) { - if (/\d{9}/.test(val.game_uid) && val.game_biz === 'hk4e_cn') { - uids.push(val.game_uid + '') - } - } - if (uids.length > 0) { - await redis.set(`Yz:genshin:mys:ltuid-uids:${ltuid}`, JSON.stringify(uids), { EX: 3600 * 24 * 90 }) - return ret('', uids) - } - return ret(msg, false) - } - /** * 检查CK状态 * @param ck 需要检查的CK @@ -376,108 +247,228 @@ export default class MysUser extends BaseModel { } } + // 不建议使用,为了兼容老数据格式,后续废弃 + getCkInfo (game = 'gs') { + let gameKey = this.gameKey(game) + return { + ck: this.ck, + uid: this.getUid(game), + qq: '', + ltuid: this.ltuid + } + } + + getUid (game = 'gs') { + return this.getUids(game)[0] + } + + getUids (game = 'gs') { + let gameKey = this.gameKey(game) + return this.uids[gameKey] || [] + } + + getMainUid () { + let ret = {} + let uids = this.uids + MysUtil.eachGame((gameKey) => { + ret[gameKey] = uids[gameKey]?.[0] || '' + }) + return ret + } + + /** + * 刷新mysUser的UID列表 + * @returns {Promise<{msg: string, status: number}>} + */ + async reqMysUid () { + let err = (msg = 'error', status = 1) => { + return { status, msg } + } + + let res = null + let msg = 'error' + for (let serv of ['mys', 'hoyolab']) { + let roleRes = await this.getGameRole(serv) + if (roleRes?.retcode === 0) { + res = roleRes + if (serv === 'hoyolab') { + this.type = 'hoyolab' + } + break + } + if (roleRes.retcode * 1 === -100) { + msg = '该ck已失效,请重新登录获取' + } + msg = roleRes.message || 'error' + } + + if (!res) return err(msg) + let playerList = res?.data?.list || [] + playerList = playerList.filter(v => ['hk4e_cn', 'hkrpg_cn', 'hk4e_global', 'hkrpg_global'].includes(v.game_biz)) + if (!playerList || playerList.length <= 0) { + return err('该账号尚未绑定原神或星穹角色') + } + + this.gsUids = [] + this.srUids = [] + + /** 米游社默认展示的角色 */ + for (let val of playerList) { + this.addUid(val.game_uid, ['hk4e_cn', 'hk4e_global'].includes(val.game_biz) ? 'gs' : 'sr') + } + await this.save() + return { status: 0, msg: '' } + } + + async getGameRole (serv = 'mys') { + let ck = this.ck + let url = { + mys: 'https://api-takumi.mihoyo.com/binding/api/getUserGameRolesByCookie', + hoyolab: 'https://api-os-takumi.mihoyo.com/binding/api/getUserGameRolesByCookie' + } + + let res = await fetch(url[serv], { method: 'get', headers: { Cookie: ck } }) + if (!res.ok) return false + res = await res.json() + + return res + } + + // 获取米游社通行证id + async getUserFullInfo (serv = 'mys') { + let ck = this.ck + let url = { + mys: 'https://bbs-api.mihoyo.com/user/wapi/getUserFullInfo?gids=2', + hoyolab: '' + } + let res = await fetch(url[serv], { + method: 'get', + headers: { + Cookie: ck, + Accept: 'application/json, text/plain, */*', + Connection: 'keep-alive', + Host: 'bbs-api.mihoyo.com', + Origin: 'https://m.bbs.mihoyo.com', + Referer: ' https://m.bbs.mihoyo.com/' + } + }) + if (!res.ok) return res + res = await res.json() + return res + } + + getCache (game = 'gs') { + if (!this.cache) { + this.cache = {} + } + const { cache } = this + if (game !== 'config') { + game = this.gameKey(game) + } + if (!cache[game]) { + cache[game] = DailyCache.create(this.type, game) + } + return cache[game] + } + + + // 初始化数据 + async initDB (db = false) { + if (this.db && !db) { + return + } + db = db && db !== true ? db : await MysUserDB.find(this.ltuid, true) + this.db = db + this.setCkData(db) + } + + // 设置ck数据 + setCkData (data = {}) { + this.ck = data.ck || this.ck || '' + this.type = data.type || this.type || 'mys' + this.device = data.device || this.device || MysUtil.getDeviceGuid() + this.uids = this.uids || {} + let self = this + MysUtil.eachGame((game) => { + self.uids[game] = data?.uids?.[game] || self.uids[game] || [] + }) + } + + async save () { + await this.db.saveDB(this) + } + // 为当前MysUser绑定uid - addUid (uid) { + addUid (uid, game = 'gs') { if (lodash.isArray(uid)) { for (let u of uid) { - this.addUid(u) + this.addUid(u, game) } return true } uid = '' + uid - if (/\d{9}/.test(uid) || uid === 'pub') { - if (!this.uids.includes(uid)) { - this.uids.push(uid) + if (/\d{9}/.test(uid)) { + let gameKey = this.gameKey(game) + let uids = this.uids[gameKey] + if (!uids.includes(uid)) { + uids.push(uid) } } return true } + hasGame (game = 'gs') { + return (this.isGs(game) ? this.gsUids : this.srUids).length > 0 + } + // 初始化当前MysUser缓存记录 - async initCache (user) { - if (!this.ltuid || !this.servCache || !this.ck) { + async initCache () { + if (!this.ltuid || !this.ck) { return } - - // 为当前MysUser添加uid查询记录 - if (!lodash.isEmpty(this.uids)) { - for (let uid of this.uids) { - if (uid !== 'pub') { - await this.addQueryUid(uid) - // 添加ltuid-uid记录,用于判定ltuid绑定个数及自ltuid查询 - await this.cache.zAdd(tables.uid, this.ltuid, uid) + let self = this + await MysUtil.eachGame(async (game) => { + let uids = self.uids[game] + await this.addQueryUid(uids, game) + let cache = self.getCache(game) + let cacheSearchList = await cache.get(tables.del, this.ltuid, true) + // 这里不直接插入,只插入当前查询记录中没有的值 + if (cacheSearchList && cacheSearchList.length > 0) { + for (let searchedUid of cacheSearchList) { + // 检查对应uid是否有新的查询记录 + if (!await this.getQueryLtuid(searchedUid, game)) { + await this.addQueryUid(searchedUid, game) + } } } - } else { - console.log(`ltuid:${this.ltuid}暂无uid信息,请检查...`) - // 公共ck暂无uid信息不添加 - if (user?.qq === 'pub') { - return false - } - } - // 缓存ckData,供后续缓存使用 - // ltuid关系存储到与server无关的cache中,方便后续检索 - if (this.ckData && this.ckData.ck) { - await this.cache.kSet(tables.ck, this.ltuid, this.ckData) - } - - // 缓存qq,用于删除ltuid时查找 - if (user && user.qq) { - let qq = user.qq === 'pub' ? 'pub' : user.qq * 1 - let qqArr = await this.cache.kGet(tables.qq, this.ltuid, true) - if (!lodash.isArray(qqArr)) { - qqArr = [] - } - if (!qqArr.includes(qq)) { - qqArr.push(qq) - await this.cache.kSet(tables.qq, this.ltuid, qqArr) - } - } - - // 从删除记录中查找并恢复查询记录 - let cacheSearchList = await this.servCache.get(tables.del, this.ltuid, true) - // 这里不直接插入,只插入当前查询记录中没有的值 - if (cacheSearchList && cacheSearchList.length > 0) { - for (let searchedUid of cacheSearchList) { - // 检查对应uid是否有新的查询记录 - if (!await this.getQueryLtuid(searchedUid)) { - await this.addQueryUid(searchedUid) - } - } - } + }) return true } - async disable () { - await this.servCache.zDel(tables.detail, this.ltuid) - logger.mark(`[标记无效ck][ltuid:${this.ltuid}]`) + async disable (game = 'gs') { + let cache = this.getCache(game) + await cache.zDel(tables.detail, this.ltuid) + logger.mark(`[标记无效ck][game:${game}, ltuid:${this.ltuid}`) } // /** * 删除缓存, 供User解绑CK时调用 - * @param user * @returns {Promise} */ - async del (user) { - if (user && user.qq) { - let qqList = await this.cache.kGet(tables.qq, this.ltuid, true) - let newList = lodash.pull(qqList, user.qq * 1) - await this.cache.kSet(tables.qq, this.ltuid, newList) - if (newList.length > 0) { - // 如果数组还有其他元素,说明该ltuid还有其他绑定,不进行缓存删除 - return false - } - } + async del () { + // TODO 检查一ltuid多绑定的情况 // 将查询过的uid缓存起来,以备后续重新绑定时恢复 - let uids = await this.getQueryUids() - await this.servCache.set(tables.del, uids) - - // 标记ltuid为失效 - await this.servCache.zDel(tables.detail, this.ltuid) - await this.cache.zDel(tables.uid, this.ltuid) - await this.cache.kDel(tables.ck, this.ltuid) - await this.cache.kDel(tables.qq, this.ltuid) + let self = this + await MysUtil.eachGame(async (game) => { + let uids = await this.getQueryUids(game) + let cache = self.getCache(game) + await cache.set(tables.del, uids) + // 标记ltuid为失效 + await cache.zDel(tables.detail, this.ltuid) + }) + await self.db.destroy() + self._delCache() logger.mark(`[删除失效ck][ltuid:${this.ltuid}]`) } @@ -498,28 +489,38 @@ export default class MysUser extends BaseModel { } // 为当前用户添加uid查询记录 - async addQueryUid (uid) { + async addQueryUid (uid, game = 'gs') { + if (lodash.isArray(uid)) { + for (let u of uid) { + await this.addQueryUid(u, game) + } + return + } if (uid) { - await this.servCache.zAdd(tables.detail, this.ltuid, uid) + let cache = this.getCache(game) + await cache.zAdd(tables.detail, this.ltuid, uid) } } // 获取当前用户已查询uid列表 - async getQueryUids () { - return await this.servCache.zList(tables.detail, this.ltuid) + async getQueryUids (game = 'gs') { + let cache = this.getCache(game) + return await cache.zList(tables.detail, this.ltuid) } // 根据uid获取查询ltuid - async getQueryLtuid (uid) { - return await this.servCache.zKey(tables.detail, uid) + async getQueryLtuid (uid, game = 'gs') { + let cache = this.getCache(game) + return await cache.zKey(tables.detail, uid) } // 检查指定uid是否为当前MysUser所有 - async ownUid (uid) { + ownUid (uid, game = 'gs') { if (!uid) { return false } - let uidArr = await this.cache.zList(tables.uid, this.ltuid) || [] - return uid && uidArr.join(',').split(',').includes(uid + '') + let gameKey = this.gameKey(game) + let uids = this.uids[gameKey] + return uids.includes(uid + '') } } diff --git a/plugins/genshin/model/mys/MysUtil.js b/plugins/genshin/model/mys/MysUtil.js new file mode 100644 index 0000000..c6b6c40 --- /dev/null +++ b/plugins/genshin/model/mys/MysUtil.js @@ -0,0 +1,49 @@ +import { Data } from '#miao' + +const games = ['gs', 'sr'] + +const MysUtil = { + // 获取标准ltuid + getLtuid (data) { + if (!data) { + return false + } + if (/^\d{4,9}$/.test(data)) { + return data + } + let testRet = /ltuid=(\d{4,9})/g.exec(data.ck || data) + if (testRet && testRet[1]) { + return testRet[1] + } + return false + }, + + // 获取标准gameKey + getGameKey (game) { + // 兼容e的处理 + if (game.user_id) { + return game.isSr ? 'sr' : 'gs' + } + return ['sr', 'star'].includes(game) ? 'sr' : 'gs' + }, + + // 生成设备guid + getDeviceGuid () { + function S4 () { + return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1) + } + + return (S4() + S4() + '-' + S4() + '-' + S4() + '-' + S4() + '-' + S4() + S4() + S4()) + }, + + // 循环game + async eachGame (fn) { + await Data.forEach(games, fn) + }, + + // 循环server + async eachServ (fn) { + await Data.forEach(['mys', 'hoyolab'], fn) + } +} +export default MysUtil diff --git a/plugins/genshin/model/mys/NoteUser.js b/plugins/genshin/model/mys/NoteUser.js index 6839526..9e62201 100644 --- a/plugins/genshin/model/mys/NoteUser.js +++ b/plugins/genshin/model/mys/NoteUser.js @@ -8,10 +8,12 @@ import BaseModel from './BaseModel.js' import lodash from 'lodash' import MysUser from './MysUser.js' -import gsCfg from '../gsCfg.js' +import MysUtil from './MysUtil.js' +import { UserDB } from '../db/index.js' +import { Data } from '#miao' export default class NoteUser extends BaseModel { - constructor (qq, data = null) { + constructor (qq) { super() // 检查实例缓存 let cacheObj = this._getThis('user', qq) @@ -19,77 +21,19 @@ export default class NoteUser extends BaseModel { return cacheObj } this.qq = qq - if (data) { - this.ckData = this.ckData || {} - for (let uid in data) { - let ck = data[uid] - if (uid && ck.uid) { - this.ckData[uid] = ck - } - } - } else if (!this.ckData) { - this._getCkData() - } - // 缓存实例 return this._cacheThis() } - // 初始化 user - /** - * 创建NoteUser实例 - * @param qq NoterUser对应id(qq) - * * 若传入e对象则会识别e.user_id,并将user对象添加至e.user - * @param data 用户对应MysCookie数据,为空则自动读取 - * @returns {Promise} - */ - static async create (qq, data = null) { - // 兼容处理传入e - if (qq && qq.user_id) { - let e = qq - let user = await NoteUser.create(e.user_id) - e.user = user - return user - } - let user = new NoteUser(qq, data) - // 检查绑定uid (regUid) - await user.getRegUid() - // 传入data则使用,否则读取 - return user - } - - static async forEach (fn) { - // 初始化用户缓存 - let res = await gsCfg.getBingCk() - for (let qq in res.noteCk) { - let cks = res.noteCk[qq] - if (!lodash.isEmpty(cks)) { - let user = await NoteUser.create(qq, cks) - if (user && fn) { - if (await fn(user) === false) { - break - } - } - } - } - } - - /** - * 获取当前用户uid - * 如果为绑定用户,优先获取ck对应uid,否则获取绑定uid - */ get uid () { - // 如果绑定有CK,则 - if (this.hasCk) { - return this.mainCk?.uid - } - return this._regUid || '' + console.log('NoteUser.uid 默认返回原神UID,可更改为 user.getUid(game)') + return this.getUid() } /** * 当前用户是否具备CK */ get hasCk () { - return this.ckData && !lodash.isEmpty(this.ckData) + return !lodash.isEmpty(this.mysUsers) } /** @@ -99,159 +43,293 @@ export default class NoteUser extends BaseModel { if (!this.hasCk) { return [] } + let ret = [] return lodash.map(this.ckData, 'uid') } - /** - * 获取当前生效CK - * - * 返回isMain的uid,没有的话返回首位 - */ - get mainCk () { - if (this.hasCk) { - return lodash.filter(this.ckData, (ck) => ck.isMain)[0] || lodash.values(this.ckData)[0] - } - return false - } - /** * 获取当前用户的所有ck * @returns { {ltuid:{ckData, ck, uids}} } */ get cks () { + console.log('NoteUser.cks 即将废弃') + let game = 'gs' let cks = {} if (!this.hasCk) { return cks } - for (let uid in this.ckData) { - let ck = this.ckData[uid] - if (ck && ck.ltuid && ck.uid) { - cks[ck.ltuid] = cks[ck.ltuid] || { - ckData: ck, - ck: ck.ck, - uids: [] + for (let ltuid in this.mysUsers) { + let mys = this.mysUsers[ltuid] + if (mys && mys.ltuid && mys.uid) { + cks[ltuid] = cks[ltuid] || { + ckData: mys.getCkInfo(game), + ck: mys.ck, + uids: mys.getUids(game) } - cks[ck.ltuid].uids.push(ck.uid) } } return cks } + /** + * 创建NoteUser实例 + * @param qq NoterUser对应id(qq) + * @param db + * * 若传入e对象则会识别e.user_id,并将user对象添加至e.user + * @param data 用户对应MysCookie数据,为空则自动读取 + * @returns {Promise} + */ + static async create (qq, db = false) { + // 兼容处理传入e + if (qq && qq.user_id) { + let e = qq + let user = await NoteUser.create(e.user_id) + e.user = user + return user + } + + let user = new NoteUser(qq) + await user.initDB(db) + + // 传入data则使用,否则读取 + return user + } + + static async forEach (fn) { + let dbs = await UserDB.findAll() + await Data.forEach(users, async (db) => { + let user = await NoteUser.create(db.id, db) + return await fn(user) + }) + } + + // 初始化数据 + async initDB (db = false) { + if (this.db && !db) { + return + } + // 为后续多类型用户兼容 + this.db = db && db !== true ? db : await UserDB.find(this.qq, 'qq') + await this.initMysUser() + this.initUids() + await this.save() + } + + // 初始化MysUser对象 + async initMysUser () { + let ltuids = this.db?.ltuids || '' + this.mysUsers = {} + for (let ltuid of ltuids.split(',')) { + let mys = await MysUser.create(ltuid) + if (mys) { + this.mysUsers[ltuid] = mys + } + } + } + + // 初始化Uid + initUids (setMainUid = {}) { + let self = this + self.mainUid = self.mainUid || {} + self.uidList = {} + self.uidMap = self.uidMap || {} + self.games = {} + const { db, mainUid, uidList, games, uidMap, mysUsers } = self + + let gameDBs = {} + lodash.forEach(db?.games, (gameDB) => { + gameDBs[gameDB.game] = gameDB + }) + + MysUtil.eachGame((key) => { + let gameDB = gameDBs[key] + uidMap[key] = {} + uidList[key] = [] + games[key] = gameDB + // 优先设置CK UID + lodash.forEach(mysUsers, (mys) => { + lodash.forEach(mys.uids[key] || [], (uid) => { + uid = uid + '' + if (uid && !uidMap[key][uid]) { + uidMap[key][uid] = { uid, type: 'ck', ltuid: mys.ltuid } + uidList[key].push(uid) + } + }) + }) + + let uidReg = /\d{9}/ + let regUidCount = 0 + + // 存在数据库记录则进行设置 + if (gameDB) { + let regUids = gameDB.data + // 依次设置verify、reg uid数据 + lodash.forEach(['verify', 'reg'], (uidType) => { + lodash.forEach(regUids, (ds, uid) => { + uid = uid + '' + if (regUidCount <= 5 && uid && uidReg.test(uid) && ds.type === uidType && !uidMap[key][uid]) { + uidMap[key][uid] = { uid, type: ds.type } + uidList[key].push(uid) + regUidCount++ + } + }) + }) + + // 如果当前选中uid未在记录中,则补充为reg数据 + let uid = gameDB.uid + if (uid && !uidMap[key][uid]) { + uid = uid + '' + uidMap[key][uid] = { uid, type: 'reg' } + uidList[key].push(uid) + } + } + // 设置选中uid + if (setMainUid === false || setMainUid[key] === false) { + mainUid[key] = uidList[key]?.[0] || '' + } else { + mainUid[key] = setMainUid[key] || mainUid[key] || gameDB?.uid || uidList[key]?.[0] || '' + } + }) + } + + async save () { + await this.db.saveDB(this) + } + + // 获取当前UID + getUid (game = 'gs') { + let gameKey = this.gameKey(game) + return this.mainUid[gameKey] || this.uidList[gameKey][0] || '' + } + + getSelfUid (game = 'gs') { + let gameKey = this.gameKey(game) + let uidList = this.uidMap[gameKey].filter((v) => v.type === 'ck') + if (uidList.length === 0) { + return false + } + let find = lodash.find(uidList, (v) => v.uid + '' === uid + '', 0) + return find ? find.uid : uidList[0].uid + } + + // 获取UID列表 + getUidList (game = 'gs') { + let ret = [] + let gameKey = this.gameKey(game) + lodash.forEach(this.uidList[gameKey], (uid) => { + ret.push(this.uidMap[gameKey][uid]) + }) + return ret + } + + // 获取当前UID数据 + getUidData (game = 'gs') { + let gameKey = this.gameKey(game) + let uid = this.getUid(game) + return this.uidMap[gameKey]?.[uid] + } + + // 获取当前的MysUser对象 + getMysUser (game = 'gs') { + if (lodash.isEmpty(this.mysUsers)) { + return false + } + let uidData = this.getUidData(game) + let ltuid = lodash.keys(this.mysUsers)[0] + if (uidData.type === 'ck') { + ltuid = uidData.ltuid + } + return this.mysUsers[ltuid] + } + + + // 添加UID + async addRegUid (uid, game = 'gs') { + let gameKey = this.gameKey(game) + uid = uid + '' + if (!this.uidMap[gameKey][uid]) { + this.uidMap[gameKey][uid] = { uid, type: 'reg' } + } + await this.save() + this.setMainUid(uid, game) + // todo 优化保存 + await this.save() + } + + // 删除UID + async delRegUid (uid, game = 'gs') { + let gameKey = this.gameKey(game) + if (this.uidMap[gameKey][uid] && this.uidMap[gameKey][uid].type !== 'ck') { + lodash.remove(this.uidList[gameKey], (u) => u + '' === uid + '') + delete this.uidMap[gameKey][uid] + } + await this.save() + if (this.mainUid[gameKey] === uid) { + this.setMainUid(this.uidList[gameKey][0], game) + await this.save() + } + } + /** * 获取当前用户的绑定UID * 主要供内部调用,建议使用 user.uid 获取用户uid * @returns {Promise<*>} */ - async getRegUid (redisKey = `Yz:genshin:mys:qq-uid:${this.qq}`) { - let uid = await redis.get(redisKey) - if (uid) { - await redis.setEx(redisKey, 3600 * 24 * 30, uid) - } - this._regUid = uid - return this._regUid + async getRegUid (game = 'gs') { + let gameKey = this.gameKey(game) + return this.mainUid[gameKey] || '' } /** * 设置当前用户的绑定uid * @param uid 要绑定的uid + * @param game * @param force 若已存在绑定uid关系是否强制更新 */ - async setRegUid (uid = '', force = false) { - let redisKey = `Yz:genshin:mys:qq-uid:${this.qq}` - if (uid && /[1|2|5-9][0-9]{8}/.test(uid)) { - uid = String(uid) - const oldUid = await this.getRegUid() - // force true、不存在绑定UID,UID一致时存储并更新有效期 - if (force || !oldUid || oldUid === uid) { - await redis.setEx(redisKey, 3600 * 24 * 30, uid) - } - this._regUid = uid - return String(this._regUid) || '' + async setRegUid (uid = '', game = 'gs', force = false) { + if (this.getRegUid(game) && !force) { + return uid } - return '' + await this.addRegUid(uid, game) + return uid } - /** - * 切换绑定CK生效的UID - * @param uid 要切换的UID - */ - async setMainUid (uid = '') { + // 切换绑定CK生效的UID + setMainUid (uid = '', game = 'gs') { + let gameKey = this.gameKey(game) // 兼容传入index - if (uid * 1 <= this.ckUids.length) uid = this.ckUids[uid] - // 非法值,以及未传入时使用当前或首个有效uid - uid = (uid || this.uid) * 1 - // 设置主uid - lodash.forEach(this.ckData, (ck) => { - ck.isMain = ck.uid * 1 === uid * 1 - }) - // 保存CK数据 - this._saveCkData() - await this.setRegUid(uid, true) + if (uid < 100 && this.uidList[gameKey][uid]) { + uid = this.uidList[gameKey][uid] + } + if (this.uidMap[gameKey][uid]) { + this.mainUid[gameKey] = uid + } + let mainUid = {} + mainUid[gameKey] = uid + this.initUids(mainUid) } - /** - * 初始化或重置 当前用户缓存 - */ - async initCache () { - // 刷新绑定CK的缓存 - let count = 0 - let cks = this.cks - for (let ltuid in cks) { - let { ckData, uids } = cks[ltuid] - let mysUser = await MysUser.create(ckData) - for (let uid of uids) { - mysUser.addUid(uid) - } - if (mysUser && await mysUser.initCache(this)) { - count++ - } - } - return count + // 添加MysUser + addMysUser (mysUser) { + this.mysUsers[mysUser.ltuid] = mysUser + this.initUids(mysUser.getMainUid()) } - /** - * 为当前用户增加CK - * @param cks 绑定的ck - */ - async addCk (cks) { - let ckData = this.ckData - lodash.forEach(cks, (ck, uid) => { - ckData[uid] = ck - }) - this._saveCkData() - await this.initCache() + // 删除当前用户绑定CK + async delCk (ltuid = '') { + console.log('delCk即将废弃') + return await this.delMysUser(ltuid) + } - /** - * 删除当前用户绑定CK - * @param ltuid 根据ltuid删除,未传入则删除当前生效uid对应ltuid - * @param needRefreshCache 是否需要刷新cache,默认刷新 - */ - async delCk (ltuid = '', needRefreshCache = true) { - if (!ltuid) { - ltuid = this.mainCk.ltuid + async delMysUser (ltuid = '') { + if (ltuid && this.mysUsers[ltuid]) { + let mys = this.mysUsers[ltuid] + delete this.mysUsers[ltuid] + await mys.del() } - let ret = [] - ltuid = ltuid * 1 - let ckData = this.ckData - for (let uid in ckData) { - let ck = ckData[uid] - if (ltuid && ck.ltuid * 1 === ltuid) { - ret.push(uid) - delete ckData[uid] - } - } - // 刷新主ck并保存ckData - await this.setMainUid() - - // 刷新MysUser缓存 - if (needRefreshCache) { - let ckUser = await MysUser.create(ltuid) - if (ckUser) { - await ckUser.del(this) - } - } - return ret + this.initUids(false) + await this.save() } /** @@ -291,15 +369,4 @@ export default class NoteUser extends BaseModel { } return ret } - - // 内部方法:读取CK数据 - _getCkData () { - this.ckData = gsCfg.getBingCkSingle(this.qq) - return this.ckData - } - - // 内部方法:写入CK数据 - _saveCkData () { - gsCfg.saveBingCk(this.qq, this.ckData) - } } diff --git a/plugins/genshin/model/mys/apiTool.js b/plugins/genshin/model/mys/apiTool.js index e986cde..9755955 100644 --- a/plugins/genshin/model/mys/apiTool.js +++ b/plugins/genshin/model/mys/apiTool.js @@ -4,140 +4,140 @@ * 临时处理,后续大概率重写 主要原因(懒) */ export default class apiTool { - /** - * - * @param {用户uid} uid - * @param {区服} server - * @param {是否为星穹铁道或其他游戏? type(bool or string)} isSr - */ - constructor(uid, server, isSr = false) { - this.uid = uid - this.isSr = isSr - this.server = server - this.game='genshin' - if(isSr) this.game='honkaisr' - if(typeof isSr !== 'boolean'){ - this.game=isSr + /** + * + * @param {用户uid} uid + * @param {区服} server + * @param {是否为星穹铁道或其他游戏? type(bool or string)} isSr + */ + constructor (uid, server, isSr = false) { + this.uid = uid + this.isSr = isSr + this.server = server + this.game = 'genshin' + if (isSr) this.game = 'honkaisr' + if (typeof isSr !== 'boolean') { + this.game = isSr + } + } + + + getUrlMap = (data = {}) => { + let host, hostRecord + if (['cn_gf01', 'cn_qd01', 'prod_gf_cn', 'prod_qd_cn'].includes(this.server)) { + host = 'https://api-takumi.mihoyo.com/' + hostRecord = 'https://api-takumi-record.mihoyo.com/' + } else if (['os_usa', 'os_euro', 'os_asia', 'os_cht'].includes(this.server)) { + host = 'https://api-os-takumi.mihoyo.com/' + hostRecord = 'https://bbs-api-os.mihoyo.com/' + } + let urlMap = { + genshin: { + /** 首页宝箱 */ + index: { + url: `${hostRecord}game_record/app/genshin/api/index`, + query: `role_id=${this.uid}&server=${this.server}` + }, + /** 深渊 */ + spiralAbyss: { + url: `${hostRecord}game_record/app/genshin/api/spiralAbyss`, + query: `role_id=${this.uid}&schedule_type=${data.schedule_type || 1}&server=${this.server}` + }, + /** 角色详情 */ + character: { + url: `${hostRecord}game_record/app/genshin/api/character`, + body: { role_id: this.uid, server: this.server } + }, + /** 树脂 */ + dailyNote: { + url: `${hostRecord}game_record/app/genshin/api/dailyNote`, + query: `role_id=${this.uid}&server=${this.server}` + }, + /** 详情 */ + detail: { + url: `${host}event/e20200928calculate/v1/sync/avatar/detail`, + query: `uid=${this.uid}®ion=${this.server}&avatar_id=${data.avatar_id}` + }, + /** 札记 */ + ys_ledger: { + url: 'https://hk4e-api.mihoyo.com/event/ys_ledger/monthInfo', + query: `month=${data.month}&bind_uid=${this.uid}&bind_region=${this.server}` + }, + /** 养成计算器 */ + compute: { + url: `${host}event/e20200928calculate/v2/compute`, + body: data + }, + blueprintCompute: { + url: `${host}event/e20200928calculate/v1/furniture/compute`, + body: data + }, + /** 养成计算器 */ + blueprint: { + url: `${host}event/e20200928calculate/v1/furniture/blueprint`, + query: `share_code=${data.share_code}®ion=${this.server}` + }, + /** 角色技能 */ + avatarSkill: { + url: `${host}event/e20200928calculate/v1/avatarSkill/list`, + query: `avatar_id=${data.avatar_id}` + }, + /** 七圣召唤数据 */ + basicInfo: { + url: `${hostRecord}game_record/app/genshin/api/gcg/basicInfo`, + query: `role_id=${this.uid}&server=${this.server}` + }, + /**使用兑换码 目前仅限国际服,来自于国服的uid请求已在myinfo.js的init方法提前拦截 */ + useCdk: { + url: 'PLACE_HOLDER', + query: null } + }, + honkaisr: { + /** 首页宝箱 */ + index: { + url: `${hostRecord}game_record/app/hkrpg/api/index`, + query: `role_id=${this.uid}&server=${this.server}` + }, + UserGame: { + url: `${host}common/badge/v1/login/account`, + body: { uid: this.uid, region: this.server, lang: 'zh-cn', game_biz: 'hkrpg_cn' } + }, + /** + * 开拓阅历接口 + */ + ys_ledger: { + url: `${host}/event/srledger/month_info`, + query: `region=${this.server}&uid=${this.uid}&month=${data.month}` + }, + /** 角色详情 */ + character: { + url: `${hostRecord}game_record/app/hkrpg/api/avatar/info`, + body: { role_id: this.uid, server: this.server } + }, + /** 树脂 */ + dailyNote: { + url: `${hostRecord}game_record/app/hkrpg/api/note`, + query: `role_id=${this.uid}&server=${this.server}` + } + } } - - getUrlMap = (data = {}) => { - let host, hostRecord - if (['cn_gf01', 'cn_qd01', 'prod_gf_cn','prod_qd_cn'].includes(this.server)) { - host = 'https://api-takumi.mihoyo.com/' - hostRecord = 'https://api-takumi-record.mihoyo.com/' - } else if (['os_usa', 'os_euro', 'os_asia', 'os_cht'].includes(this.server)) { - host = 'https://api-os-takumi.mihoyo.com/' - hostRecord = 'https://bbs-api-os.mihoyo.com/' - } - let urlMap = { - genshin: { - /** 首页宝箱 */ - index: { - url: `${hostRecord}game_record/app/genshin/api/index`, - query: `role_id=${this.uid}&server=${this.server}` - }, - /** 深渊 */ - spiralAbyss: { - url: `${hostRecord}game_record/app/genshin/api/spiralAbyss`, - query: `role_id=${this.uid}&schedule_type=${data.schedule_type || 1}&server=${this.server}` - }, - /** 角色详情 */ - character: { - url: `${hostRecord}game_record/app/genshin/api/character`, - body: { role_id: this.uid, server: this.server } - }, - /** 树脂 */ - dailyNote: { - url: `${hostRecord}game_record/app/genshin/api/dailyNote`, - query: `role_id=${this.uid}&server=${this.server}` - }, - /** 详情 */ - detail: { - url: `${host}event/e20200928calculate/v1/sync/avatar/detail`, - query: `uid=${this.uid}®ion=${this.server}&avatar_id=${data.avatar_id}` - }, - /** 札记 */ - ys_ledger: { - url: 'https://hk4e-api.mihoyo.com/event/ys_ledger/monthInfo', - query: `month=${data.month}&bind_uid=${this.uid}&bind_region=${this.server}` - }, - /** 养成计算器 */ - compute: { - url: `${host}event/e20200928calculate/v2/compute`, - body: data - }, - blueprintCompute: { - url: `${host}event/e20200928calculate/v1/furniture/compute`, - body: data - }, - /** 养成计算器 */ - blueprint: { - url: `${host}event/e20200928calculate/v1/furniture/blueprint`, - query: `share_code=${data.share_code}®ion=${this.server}` - }, - /** 角色技能 */ - avatarSkill: { - url: `${host}event/e20200928calculate/v1/avatarSkill/list`, - query: `avatar_id=${data.avatar_id}` - }, - /** 七圣召唤数据 */ - basicInfo: { - url: `${hostRecord}game_record/app/genshin/api/gcg/basicInfo`, - query: `role_id=${this.uid}&server=${this.server}` - }, - /**使用兑换码 目前仅限国际服,来自于国服的uid请求已在myinfo.js的init方法提前拦截 */ - useCdk: { - url: 'PLACE_HOLDER', - query: null - } - }, - honkaisr: { - /** 首页宝箱 */ - index: { - url: `${hostRecord}game_record/app/hkrpg/api/index`, - query: `role_id=${this.uid}&server=${this.server}` - }, - UserGame:{ - url:`${host}common/badge/v1/login/account`, - body: { uid: this.uid, region: this.server,lang:'zh-cn',game_biz:'hkrpg_cn' } - }, - /** - * 开拓阅历接口 - */ - ys_ledger:{ - url:`${host}/event/srledger/month_info`, - query:`region=${this.server}&uid=${this.uid}&month=${data.month}` - }, - /** 角色详情 */ - character: { - url: `${hostRecord}game_record/app/hkrpg/api/avatar/info`, - body: { role_id: this.uid, server: this.server } - }, - /** 树脂 */ - dailyNote: { - url: `${hostRecord}game_record/app/hkrpg/api/note`, - query: `role_id=${this.uid}&server=${this.server}` - }, - } - } - - if (this.server.startsWith('os')) { - urlMap.genshin.detail.url = 'https://sg-public-api.hoyolab.com/event/calculateos/sync/avatar/detail'// 角色天赋详情 - urlMap.genshin.detail.query = `lang=zh-cn&uid=${this.uid}®ion=${this.server}&avatar_id=${data.avatar_id}` - urlMap.genshin.avatarSkill.url = 'https://sg-public-api.hoyolab.com/event/calculateos/avatar/skill_list'// 查询未持有的角色天赋 - urlMap.genshin.avatarSkill.query = `lang=zh-cn&avatar_id=${data.avatar_id}` - urlMap.genshin.compute.url = 'https://sg-public-api.hoyolab.com/event/calculateos/compute'// 已支持养成计算 - urlMap.genshin.blueprint.url = 'https://sg-public-api.hoyolab.com/event/calculateos/furniture/blueprint' - urlMap.genshin.blueprint.query = `share_code=${data.share_code}®ion=${this.server}&lang=zh-cn` - urlMap.genshin.blueprintCompute.url = 'https://sg-public-api.hoyolab.com/event/calculateos/furniture/compute' - urlMap.genshin.blueprintCompute.body = { lang: 'zh-cn', ...data } - urlMap.genshin.ys_ledger.url = 'https://hk4e-api-os.mihoyo.com/event/ysledgeros/month_info'// 支持了国际服札记 - urlMap.genshin.ys_ledger.query = `lang=zh-cn&month=${data.month}&uid=${this.uid}®ion=${this.server}` - urlMap.genshin.useCdk.url = 'https://sg-hk4e-api.hoyoverse.com/common/apicdkey/api/webExchangeCdkey' - urlMap.genshin.useCdk.query = `uid=${this.uid}®ion=${this.server}&lang=zh-cn&cdkey=${data.cdk}&game_biz=hk4e_global` - } - return urlMap[this.game] + if (this.server.startsWith('os')) { + urlMap.genshin.detail.url = 'https://sg-public-api.hoyolab.com/event/calculateos/sync/avatar/detail'// 角色天赋详情 + urlMap.genshin.detail.query = `lang=zh-cn&uid=${this.uid}®ion=${this.server}&avatar_id=${data.avatar_id}` + urlMap.genshin.avatarSkill.url = 'https://sg-public-api.hoyolab.com/event/calculateos/avatar/skill_list'// 查询未持有的角色天赋 + urlMap.genshin.avatarSkill.query = `lang=zh-cn&avatar_id=${data.avatar_id}` + urlMap.genshin.compute.url = 'https://sg-public-api.hoyolab.com/event/calculateos/compute'// 已支持养成计算 + urlMap.genshin.blueprint.url = 'https://sg-public-api.hoyolab.com/event/calculateos/furniture/blueprint' + urlMap.genshin.blueprint.query = `share_code=${data.share_code}®ion=${this.server}&lang=zh-cn` + urlMap.genshin.blueprintCompute.url = 'https://sg-public-api.hoyolab.com/event/calculateos/furniture/compute' + urlMap.genshin.blueprintCompute.body = { lang: 'zh-cn', ...data } + urlMap.genshin.ys_ledger.url = 'https://hk4e-api-os.mihoyo.com/event/ysledgeros/month_info'// 支持了国际服札记 + urlMap.genshin.ys_ledger.query = `lang=zh-cn&month=${data.month}&uid=${this.uid}®ion=${this.server}` + urlMap.genshin.useCdk.url = 'https://sg-hk4e-api.hoyoverse.com/common/apicdkey/api/webExchangeCdkey' + urlMap.genshin.useCdk.query = `uid=${this.uid}®ion=${this.server}&lang=zh-cn&cdkey=${data.cdk}&game_biz=hk4e_global` } + return urlMap[this.game] + } } diff --git a/plugins/genshin/model/mys/mysInfo.js b/plugins/genshin/model/mys/mysInfo.js index c04e2fd..5feb440 100644 --- a/plugins/genshin/model/mys/mysInfo.js +++ b/plugins/genshin/model/mys/mysInfo.js @@ -25,7 +25,7 @@ export default class MysInfo { } // ck对应MysUser对象 this.ckUser = null - this.auth = ['dailyNote', 'bbs_sign_info', 'bbs_sign_home', 'bbs_sign', 'ys_ledger', 'compute', 'avatarSkill', 'detail', 'blueprint'] + this.auth = ['dailyNote', 'bbs_sign_info', 'bbs_sign_home', 'bbs_sign', 'ys_ledger', 'compute', 'avatarSkill', 'detail', 'blueprint', 'UserGame'] } static async init (e, api) { @@ -62,7 +62,7 @@ export default class MysInfo { mysInfo.e.uid = mysInfo.uid /** 获取ck */ - await mysInfo.getCookie(onlySelfCk) + await mysInfo.getCookie(e, onlySelfCk) /** 判断回复 */ await mysInfo.checkReply() @@ -75,7 +75,7 @@ export default class MysInfo { let user = await NoteUser.create(e) if (user) { // 强制读取一次ck,防止一些问题 - user._getCkData() + user.initDB(true) return user } return false @@ -91,7 +91,7 @@ export default class MysInfo { let user = await NoteUser.create(e) if (e.uid && matchMsgUid) { /** 没有绑定的自动绑定 */ - return await user.setRegUid(e.uid, false) + return await user.setRegUid(e.uid, e, false) } let { msg = '', at = '' } = e @@ -101,7 +101,7 @@ export default class MysInfo { /** at用户 */ if (at) { let atUser = await NoteUser.create(at) - uid = atUser.uid + uid = atUser.getUid(e) if (uid) return String(uid) if (e.noTips !== true) e.reply('尚未绑定uid', false, { at }) return false @@ -114,11 +114,11 @@ export default class MysInfo { } // 消息携带UID、当前用户UID、群名片携带UID 依次获取 - uid = matchUid(msg) || user.uid || matchUid(e.sender.card) - if (!matchMsgUid) uid = user.uid + uid = matchUid(msg) || user.getUid(e) || matchUid(e.sender.card) + if (!matchMsgUid) uid = user.getUid(e) if (uid) { /** 没有绑定的自动绑定 */ - return await user.setRegUid(uid, false) + return await user.setRegUid(uid, e, false) } if (e.noTips !== true) e.reply('请先#绑定uid', false, { at }) @@ -143,24 +143,7 @@ export default class MysInfo { return false } - return selfUser.uid - } - - /** 判断绑定ck才能查询 */ - checkAuth (api) { - if (api === 'cookie') { - return true - } - if (lodash.isObject(api)) { - for (let i in api) { - if (this.auth.includes(i)) { - return true - } - } - } else if (this.auth.includes(api)) { - return true - } - return false + return selfUser.getUid(e) } /** @@ -187,7 +170,7 @@ export default class MysInfo { if (!mysInfo.uid || !mysInfo.ckInfo.ck) return false e.uid = mysInfo.uid - let mysApi = new MysApi(mysInfo.uid, mysInfo.ckInfo.ck, option,e.isSr) + let mysApi = new MysApi(mysInfo.uid, mysInfo.ckInfo.ck, option, e.isSr) let res if (lodash.isObject(api)) { @@ -220,50 +203,11 @@ export default class MysInfo { return res } - async checkReply () { - if (this.e.noTips === true) return - - if (!this.uid) { - this.e.reply('请先#绑定uid') - } - - if (!this.ckInfo.ck) { - this.e.reply('暂无可用CK,请绑定更多用户或设置公共ck..') - } - - this.e.noTips = true - } - - /* 获取请求所需ck */ - /** - * 获取请求所需CK - * @param onlySelfCk 是否只获取uid自己对应的ck。为true则只获取uid对应ck,若无则返回为空 - * @returns {Promise} 查询ck,获取失败则返回空 - */ - async getCookie(onlySelfCk = false) { - if (this.ckInfo.ck) return this.ckInfo.ck - - let mysUser = await MysUser.getByQueryUid(this.uid, onlySelfCk) - if (mysUser) { - if (mysUser.ckData?.ck) { - this.ckInfo = mysUser.ckData - this.ckUser = mysUser - // 暂时直接记录请求uid,后期优化分析MysApi请求结果分状态记录结果 - await mysUser.addQueryUid(this.uid) - } else { - // 重新分配 - await mysUser.disable() - return onlySelfCk ? '' : await this.getCookie() - } - } - return this.ckInfo.ck - } - /** * 初始化公共CK * @returns {Promise} */ - static async initPubCk() { + static async initPubCk () { // 初始化公共CK let pubCount = 0 let pubCks = GsCfg.getConfig('mys', 'pubCk') || [] @@ -287,11 +231,14 @@ export default class MysInfo { * 默认会将用户CK加入查询池 * @returns {Promise} */ - static async initUserCk() { + static async initUserCk () { // 初始化用户缓存 let userCount = 0 - await NoteUser.forEach(async function (user) { - userCount += await user.initCache(true) + await MysUser.forEach(async (mys) => { + let ret = await mys.initCache() + if (ret) { + userCount++ + } }) logger.mark(`加载用户UID:${userCount}个,加入查询池`) } @@ -302,7 +249,7 @@ export default class MysInfo { * @param clearData 强制初始化时是否清除已有数据 (刷新/重置) * @returns {Promise} */ - static async initCache(force = false, clearData = false) { + static async initCache (force = false, clearData = false) { // 检查缓存标记 let cache = DailyCache.create() if (!force && await cache.get('cache-ready')) { @@ -325,7 +272,82 @@ export default class MysInfo { return true } - async checkCode(res, type) { + static async getBingCkUid () { + let res = await GsCfg.getBingCk() + return { ...res.ck } + } + + // 获取uid绑定的ck信息 + static async checkUidBing (uid, game = 'gs') { + let ckUser = await MysUser.getByQueryUid(uid, game, true) + if (ckUser && ckUser.ck) { + return ckUser + } + return false + } + + static async delDisable () { + return await MysUser.delDisable() + } + + /** 判断绑定ck才能查询 */ + checkAuth (api) { + if (api === 'cookie') { + return true + } + if (lodash.isObject(api)) { + for (let i in api) { + if (this.auth.includes(i)) { + return true + } + } + } else if (this.auth.includes(api)) { + return true + } + return false + } + + async checkReply () { + if (this.e.noTips === true) return + + if (!this.uid) { + this.e.reply('请先#绑定uid') + } + + if (!this.ckInfo.ck) { + this.e.reply('暂无可用CK,请绑定更多用户或设置公共ck..') + } + + this.e.noTips = true + } + + /* 获取请求所需ck */ + /** + * 获取请求所需CK + * @param game 游戏 + * @param onlySelfCk 是否只获取uid自己对应的ck。为true则只获取uid对应ck,若无则返回为空 + * @returns {Promise} 查询ck,获取失败则返回空 + */ + async getCookie (game = 'gs', onlySelfCk = false) { + if (this.ckUser?.ck) return this.ckUser?.ck + + let mysUser = await MysUser.getByQueryUid(this.uid, game, onlySelfCk) + if (mysUser) { + if (mysUser.ck) { + this.ckInfo = mysUser.getCkInfo() + this.ckUser = mysUser + // 暂时直接记录请求uid,后期优化分析MysApi请求结果分状态记录结果 + await mysUser.addQueryUid(this.uid, game) + } else { + // 重新分配 + await mysUser.disable(game) + return onlySelfCk ? '' : await this.getCookie() + } + } + return this.ckUser?.ck + } + + async checkCode (res, type) { if (!res) { this.e.reply('米游社接口请求失败,暂时无法查询') return false @@ -394,7 +416,7 @@ export default class MysInfo { } /** 删除失效ck */ - async delCk() { + async delCk () { if (!this.ckUser) { return false } @@ -404,26 +426,8 @@ export default class MysInfo { } /** 查询次数满,今日内标记失效 */ - async disableToday() { + async disableToday (game = 'gs') { /** 统计次数设为超限 */ - await this.ckUser.disable() - } - - static async getBingCkUid() { - let res = await GsCfg.getBingCk() - return { ...res.ck } - } - - // 获取uid绑定的ck信息 - static async checkUidBing(uid) { - let ckUser = await MysUser.getByQueryUid(uid, true) - if (ckUser && ckUser.ckData) { - return ckUser.ckData - } - return false - } - - static async delDisable() { - return await MysUser.delDisable() + await this.ckUser.disable(game) } } diff --git a/plugins/genshin/model/note.js b/plugins/genshin/model/note.js index 6603362..8b8e2cd 100644 --- a/plugins/genshin/model/note.js +++ b/plugins/genshin/model/note.js @@ -1,182 +1,187 @@ -import moment from "moment"; -import lodash from "lodash"; -import base from "./base.js"; -import MysInfo from "./mys/mysInfo.js"; +import moment from 'moment' +import lodash from 'lodash' +import base from './base.js' +import MysInfo from './mys/mysInfo.js' export default class Note extends base { - constructor(e) { - super(e); - this.model = "dailyNote"; + constructor (e) { + super(e) + this.model = 'dailyNote' } /** 生成体力图片 */ - static async get(e) { - let note = new Note(e); - return await note.getData(); + static async get (e) { + let note = new Note(e) + return await note.getData() } - async getData() { - let res = await MysInfo.get(this.e, "dailyNote"); - let resUser; - if (!res || res.retcode !== 0) return false; + async getData () { + let res = await MysInfo.get(this.e, 'dailyNote') + let resUser + if (!res || res.retcode !== 0) return false + console.log(this.e.isSr, res) /** 截图数据 */ - let data = this.e.isSr ? this.noteSr(res) : this.noteData(res); - let screenData = this.screenData; + let data = this.e.isSr ? this.noteSr(res) : this.noteData(res) + console.log(data) + let screenData = this.screenData if (this.e.isSr) { - screenData.tplFile = "./plugins/genshin/resources/StarRail/html/dailyNote/dailyNote.html"; - resUser = await MysInfo.get(this.e,'UserGame') - if (!resUser || resUser.retcode !== 0) return false; + screenData.tplFile = './plugins/genshin/resources/StarRail/html/dailyNote/dailyNote.html' + resUser = await MysInfo.get(this.e, 'UserGame') + console.log('resUser', resUser) + if (!resUser || resUser.retcode !== 0) return false } return { name: this.e.sender.card, quality: 80, ...screenData, - ...data,...resUser?.data - }; + ...data, ...resUser?.data + } } - noteSr(res) { - let { data } = res; - let nowDay = moment().date(); - let nowUnix = Number(moment().format("X")); + + noteSr (res) { + let { data } = res + let nowDay = moment().date() + let nowUnix = Number(moment().format('X')) /** 树脂 */ - let resinMaxTime; + let resinMaxTime if (data.stamina_recover_time > 0) { - let d = moment.duration(data.stamina_recover_time, 'seconds'); - let day= Math.floor(d.asDays()); - let hours =d.hours() - let minutes =d.minutes() - let seconds =d.seconds() - resinMaxTime = hours+'小时'+minutes+'分钟'+seconds+'秒' + let d = moment.duration(data.stamina_recover_time, 'seconds') + let day = Math.floor(d.asDays()) + let hours = d.hours() + let minutes = d.minutes() + let seconds = d.seconds() + resinMaxTime = hours + '小时' + minutes + '分钟' + seconds + '秒' //精确到秒。。。。 - if(day>0){ - resinMaxTime =day+'天'+hours+'小时'+minutes+'分钟'+seconds+'秒' - }else if(hours>0){ - resinMaxTime = hours+'小时'+minutes+'分钟'+seconds+'秒' - }else if(minutes>0){ - resinMaxTime = minutes+'分钟'+seconds+'秒' - }else if(seconds>0){ - resinMaxTime = seconds+'秒' + if (day > 0) { + resinMaxTime = day + '天' + hours + '小时' + minutes + '分钟' + seconds + '秒' + } else if (hours > 0) { + resinMaxTime = hours + '小时' + minutes + '分钟' + seconds + '秒' + } else if (minutes > 0) { + resinMaxTime = minutes + '分钟' + seconds + '秒' + } else if (seconds > 0) { + resinMaxTime = seconds + '秒' } } - data.bfStamina = data.current_stamina / data.max_stamina * 100 +'%'; + data.bfStamina = data.current_stamina / data.max_stamina * 100 + '%' /** 派遣 */ - for(let item of data.expeditions){ - let d = moment.duration(item.remaining_time, 'seconds'); - let day= Math.floor(d.asDays()); - let hours =d.hours() - let minutes =d.minutes() - item.dateTime=([day+'天',hours+'时',minutes+'分'].filter(v => !['0天','0时','0分'].includes(v))).join('') - item.bfTime=(72000-item.remaining_time)/72000 *100 +'%' - if(item.avatars.length==1){ + for (let item of data.expeditions) { + let d = moment.duration(item.remaining_time, 'seconds') + let day = Math.floor(d.asDays()) + let hours = d.hours() + let minutes = d.minutes() + item.dateTime = ([day + '天', hours + '时', minutes + '分'].filter(v => !['0天', '0时', '0分'].includes(v))).join('') + item.bfTime = (72000 - item.remaining_time) / 72000 * 100 + '%' + if (item.avatars.length == 1) { item.avatars.push('派遣头像') } } // 标识属性图标~ - let icon = lodash.sample(['希儿','白露','艾丝妲','布洛妮娅','姬子','卡芙卡','克拉拉','停云','佩拉','黑塔','希露瓦','银狼']) + let icon = lodash.sample(['希儿', '白露', '艾丝妲', '布洛妮娅', '姬子', '卡芙卡', '克拉拉', '停云', '佩拉', '黑塔', '希露瓦', '银狼']) let week = [ - "星期日", - "星期一", - "星期二", - "星期三", - "星期四", - "星期五", - "星期六", - ]; - let day = `${week[moment().day()]}`; + '星期日', + '星期一', + '星期二', + '星期三', + '星期四', + '星期五', + '星期六' + ] + let day = `${week[moment().day()]}` return { uid: this.e.uid, - saveId: this.e.uid,icon,day, - resinMaxTime,nowDay:moment(new Date()).format('YYYY年MM月DD日'), - ...data, - }; + saveId: this.e.uid, icon, day, + resinMaxTime, nowDay: moment(new Date()).format('YYYY年MM月DD日'), + ...data + } } - noteData(res) { - let { data } = res; - let nowDay = moment().date(); - let nowUnix = Number(moment().format("X")); + noteData (res) { + let { data } = res + + let nowDay = moment().date() + let nowUnix = Number(moment().format('X')) /** 树脂 */ - let resinMaxTime; + let resinMaxTime if (data.resin_recovery_time > 0) { - resinMaxTime = nowUnix + Number(data.resin_recovery_time); + resinMaxTime = nowUnix + Number(data.resin_recovery_time) - let maxDate = moment.unix(resinMaxTime); - resinMaxTime = maxDate.format("HH:mm"); + let maxDate = moment.unix(resinMaxTime) + resinMaxTime = maxDate.format('HH:mm') if (maxDate.date() != nowDay) { - resinMaxTime = `明天 ${resinMaxTime}`; + resinMaxTime = `明天 ${resinMaxTime}` } else { - resinMaxTime = ` ${resinMaxTime}`; + resinMaxTime = ` ${resinMaxTime}` } } /** 派遣 */ - let remainedTime = ""; + let remainedTime = '' if (data.expeditions && data.expeditions.length >= 1) { - remainedTime = lodash.map(data.expeditions, "remained_time"); - remainedTime = lodash.min(remainedTime); + remainedTime = lodash.map(data.expeditions, 'remained_time') + remainedTime = lodash.min(remainedTime) if (remainedTime > 0) { - remainedTime = nowUnix + Number(remainedTime); - let remainedDate = moment.unix(remainedTime); - remainedTime = remainedDate.format("HH:mm"); + remainedTime = nowUnix + Number(remainedTime) + let remainedDate = moment.unix(remainedTime) + remainedTime = remainedDate.format('HH:mm') if (remainedDate.date() != nowDay) { - remainedTime = `明天 ${remainedTime}`; + remainedTime = `明天 ${remainedTime}` } else { - remainedTime = ` ${remainedTime}`; + remainedTime = ` ${remainedTime}` } } } /** 宝钱 */ - let coinTime = ""; + let coinTime = '' if (data.home_coin_recovery_time > 0) { - let coinDay = Math.floor(data.home_coin_recovery_time / 3600 / 24); - let coinHour = Math.floor((data.home_coin_recovery_time / 3600) % 24); - let coinMin = Math.floor((data.home_coin_recovery_time / 60) % 60); + let coinDay = Math.floor(data.home_coin_recovery_time / 3600 / 24) + let coinHour = Math.floor((data.home_coin_recovery_time / 3600) % 24) + let coinMin = Math.floor((data.home_coin_recovery_time / 60) % 60) if (coinDay > 0) { - coinTime = `${coinDay}天${coinHour}小时${coinMin}分钟`; + coinTime = `${coinDay}天${coinHour}小时${coinMin}分钟` } else { let coinDate = moment.unix( nowUnix + Number(data.home_coin_recovery_time) - ); + ) if (coinDate.date() != nowDay) { - coinTime = `明天 ${coinDate.format("HH:mm")}`; + coinTime = `明天 ${coinDate.format('HH:mm')}` } else { - coinTime = coinDate.format("HH:mm"); + coinTime = coinDate.format('HH:mm') } } } let week = [ - "星期日", - "星期一", - "星期二", - "星期三", - "星期四", - "星期五", - "星期六", - ]; - let day = `${moment().format("MM-DD HH:mm")} ${week[moment().day()]}`; + '星期日', + '星期一', + '星期二', + '星期三', + '星期四', + '星期五', + '星期六' + ] + let day = `${moment().format('MM-DD HH:mm')} ${week[moment().day()]}` /** 参量质变仪 */ if (data?.transformer?.obtained) { - data.transformer.reached = data.transformer.recovery_time.reached; - let recoveryTime = ""; + data.transformer.reached = data.transformer.recovery_time.reached + let recoveryTime = '' if (data.transformer.recovery_time.Day > 0) { - recoveryTime += `${data.transformer.recovery_time.Day}天`; + recoveryTime += `${data.transformer.recovery_time.Day}天` } if (data.transformer.recovery_time.Hour > 0) { - recoveryTime += `${data.transformer.recovery_time.Hour}小时`; + recoveryTime += `${data.transformer.recovery_time.Hour}小时` } if (data.transformer.recovery_time.Minute > 0) { - recoveryTime += `${data.transformer.recovery_time.Minute}分钟`; + recoveryTime += `${data.transformer.recovery_time.Minute}分钟` } - data.transformer.recovery_time = recoveryTime; + data.transformer.recovery_time = recoveryTime } return { @@ -186,7 +191,7 @@ export default class Note extends base { remainedTime, coinTime, day, - ...data, - }; + ...data + } } } diff --git a/plugins/genshin/model/roleList.js b/plugins/genshin/model/roleList.js index c61b3a6..d47debd 100644 --- a/plugins/genshin/model/roleList.js +++ b/plugins/genshin/model/roleList.js @@ -28,7 +28,7 @@ export default class RoleList extends base { if (avatars.length <= 0) return false /** 判断是否绑定了ck */ - this.ck = await MysInfo.checkUidBing(uid) + this.ck = await MysInfo.checkUidBing(uid, this.e) let skill = [] if (this.ck) { diff --git a/plugins/genshin/model/today.js b/plugins/genshin/model/today.js index 80e5c39..1549113 100644 --- a/plugins/genshin/model/today.js +++ b/plugins/genshin/model/today.js @@ -145,7 +145,7 @@ export default class Today extends base { } /** 判断是否绑定了ck */ - this.ck = await MysInfo.checkUidBing(this.e.uid) + this.ck = await MysInfo.checkUidBing(this.e.uid, this.e) let skill = {} if (this.ck) { diff --git a/plugins/genshin/model/user.js b/plugins/genshin/model/user.js index 9573bb8..9750a06 100644 --- a/plugins/genshin/model/user.js +++ b/plugins/genshin/model/user.js @@ -3,8 +3,12 @@ import gsCfg from './gsCfg.js' import lodash from 'lodash' import fs from 'node:fs' import common from '../../../lib/common/common.js' -import MysUser from './mys/MysUser.js' import MysInfo from './mys/mysInfo.js' +import NoteUser from './mys/NoteUser.js' +import MysUser from './mys/MysUser.js' +import { promisify } from 'node:util' +import YAML from 'yaml' +import { Data } from '#miao' export default class User extends base { constructor (e) { @@ -23,7 +27,7 @@ export default class User extends base { // 获取当前user实例 async user () { - return await MysInfo.getNoteUser(this.e) + return await NoteUser.create(this.e) } async resetCk () { @@ -41,9 +45,9 @@ export default class User extends base { return } - let ck = this.e.ck.replace(/#|'|"/g, '') + let ckStr = this.e.ck.replace(/#|'|"/g, '') let param = {} - ck.split(';').forEach((v) => { + ckStr.split(';').forEach((v) => { // 处理分割特殊cookie_token let tmp = lodash.trim(v).replace('=', '~').split('~') param[tmp[0]] = tmp[1] @@ -54,56 +58,62 @@ export default class User extends base { return } - this.ck = `ltoken=${param.ltoken};ltuid=${param.ltuid || param.login_uid};cookie_token=${param.cookie_token || param.cookie_token_v2}; account_id=${param.ltuid || param.login_uid};` + // TODO:独立的mys数据,不走缓存ltuid + let mys = await MysUser.create(param.ltuid) + let data = {} + data.ck = `ltoken=${param.ltoken};ltuid=${param.ltuid || param.login_uid};cookie_token=${param.cookie_token || param.cookie_token_v2}; account_id=${param.ltuid || param.login_uid};` let flagV2 = false + if (param.cookie_token_v2 && (param.account_mid_v2 || param.ltmid_v2)) { // // account_mid_v2 为版本必须带的字段,不带的话会一直提示绑定cookie失败 请重新登录 flagV2 = true - this.ck = `account_mid_v2=${param.account_mid_v2};cookie_token_v2=${param.cookie_token_v2};ltoken_v2=${param.ltoken_v2};ltmid_v2=${param.ltmid_v2};` + data.ck = `ltuid=${param.ltuid || param.login_uid};account_mid_v2=${param.account_mid_v2};cookie_token_v2=${param.cookie_token_v2};ltoken_v2=${param.ltoken_v2};ltmid_v2=${param.ltmid_v2};` + } + if (param.mi18nLang) { + data.ck += ` mi18nLang=${param.mi18nLang};` } /** 拼接ck */ - this.ltuid = param.ltuid || param.ltmid_v2 + data.ltuid = param.ltuid || param.ltmid_v2 /** 米游币签到字段 */ - this.login_ticket = param.login_ticket ?? '' + data.login_ticket = param.login_ticket ?? '' + + mys.setCkData(data) /** 检查ck是否失效 */ - if (!await this.checkCk(param)) { + let uidRet = await mys.reqMysUid() + if (uidRet.status !== 0) { logger.mark(`绑定cookie错误1:${this.checkMsg || 'cookie错误'}`) - await this.e.reply(`绑定cookie失败:${this.checkMsg || 'cookie错误'}`) - return + // 清除mys数据 + mys._delCache() + return await this.e.reply(`绑定cookie失败:${this.checkMsg || 'cookie错误'}`) } if (flagV2) { // 获取米游社通行证id - let userFullInfo = await this.getUserInfo() + let userFullInfo = await mys.getUserFullInfo() if (userFullInfo?.data?.user_info) { let userInfo = userFullInfo?.data?.user_info - this.ltuid = userInfo.uid - this.ck = `${this.ck}ltuid=${this.ltuid};` + // this.ltuid = userInfo.uid + // this.ck = `${this.ck}ltuid=${this.ltuid};` } else { logger.mark(`绑定cookie错误2:${userFullInfo.message || 'cookie错误'}`) - await this.e.reply(`绑定cookie失败:${userFullInfo.message || 'cookie错误'}`) - return + return await this.e.reply(`绑定cookie失败:${userFullInfo.message || 'cookie错误'}`) } } - logger.mark(`${this.e.logFnc} 检查cookie正常 [uid:${this.uid}]`) + logger.mark(`${this.e.logFnc} 检查cookie正常 [ltuid:${mys.ltuid}]`) - await user.addCk(this.getCk()) + await user.addMysUser(mys) + await mys.initCache() + await user.save() - logger.mark(`${this.e.logFnc} 保存cookie成功 [uid:${this.uid}] [ltuid:${this.ltuid}]`) + logger.mark(`${this.e.logFnc} 保存cookie成功 [ltuid:${mys.ltuid}]`) - let uidMsg = [`绑定cookie成功\n${this.region_name}:${this.uid}`] - if (!lodash.isEmpty(this.allUid)) { - this.allUid.forEach(v => { - uidMsg.push(`${v.region_name}:${v.uid}`) - }) - } + let uidMsg = [`绑定cookie成功`] await this.e.reply(uidMsg.join('\n')) let msg = '' - this.region_name += lodash.map(this.allUid, 'region_name').join(',') - if (/天空岛|世界树|America Server|Europe Server|Asia Server/.test(this.region_name)) { + if (mys.hasGame('gs')) { msg += '原神模块支持:\n【#体力】查询当前树脂' msg += '\n【#签到】米游社原神自动签到' msg += '\n【#关闭签到】开启或关闭原神自动签到' @@ -115,7 +125,7 @@ export default class User extends base { msg += '\n【#我的ck】查看当前绑定ck' msg += '\n【#删除ck】删除当前绑定ck' } - if (/星穹列车/.test(this.region_name)) { + if (mys.hasGame('sr')) { msg += '\n星穹铁道支持:\n功能还在咕咕咕~' } msg += '\n 支持绑定多个ck' @@ -124,110 +134,16 @@ export default class User extends base { await this.e.reply(msg) } - /** 检查ck是否可用 */ - async checkCk (param) { - let res - for (let type of ['mys', 'hoyolab']) { - let roleRes = await this.getGameRoles(type) - if (roleRes?.retcode === 0) { - res = roleRes - /** 国际服的标记 */ - if (type === 'hoyolab' && typeof (param.mi18nLang) === 'string') { - this.ck += ` mi18nLang=${param.mi18nLang};` - } - break - } - if (roleRes.retcode === -100) { - this.checkMsg = '该ck已失效,请重新登录获取' - } else { - this.checkMsg = roleRes.message || 'error' - } - } - - if (!res) return false - - if (!res.data.list || res.data.list.length <= 0) { - this.checkMsg = '该账号尚未绑定原神或星穹角色!' - return false - } else { - res.data.list = res.data.list.filter(v => ['hk4e_cn', 'hkrpg_cn', 'hk4e_global', 'hkrpg_global'].includes(v.game_biz)) - } - - //避免同时多个默认展示角色时候只绑定一个 - let is_chosen = false - /** 米游社默认展示的角色 */ - for (let val of res.data.list) { - if (val.is_chosen && !is_chosen) { - this.uid = val.game_uid - this.region_name = val.region_name - is_chosen = true - } else { - this.allUid.push({ - uid: val.game_uid, - region_name: val.region_name - }) - } - } - - - if (!this.uid && res.data?.list?.length > 0) { - this.uid = res.data.list[0].game_uid - this.region_name = res.data.list[0].region_name - if (this.allUid[0].uid == this.uid) delete this.allUid[0] - } - - return this.uid - } - - async getGameRoles (server = 'mys') { - return await MysUser.getGameRole(this.ck, server) - } - - // 获取米游社通行证id - async getUserInfo (server = 'mys') { - return await MysUser.getUserFullInfo(this.ck, server) - } - - /** 保存ck */ - getCk () { - let ck = gsCfg.getBingCkSingle(this.e.user_id) - - lodash.map(ck, o => { - o.isMain = false - return o - }) - - ck[this.uid] = { - uid: this.uid, - qq: this.e.user_id, - ck: this.ck, - ltuid: this.ltuid, - login_ticket: this.login_ticket, - region_name: this.region_name, - device_id: this.getGuid(), - isMain: true - } - - this.allUid.forEach((v) => { - if (!v.uid) return - ck[v.uid] = { - uid: v.uid, - qq: this.e.user_id, - ck: this.ck, - ltuid: this.ltuid, - region_name: v.region_name, - device_id: this.getGuid(), - isMain: false - } - }) - return ck - } - /** 删除绑定ck */ - async delCk (uid = '') { + async delCk () { let user = await this.user() - let uids = await user.delCk() - return `绑定cookie已删除,uid:${uids.join(',')}` + // 获取当前uid + let uidData = user.getUidData(this.e) + if (!uidData || uidData.type !== 'ck' || !uidData.ltuid) { + return `删除失败:当前的UID${uidData.uid}无CK信息` + } + await user.delMysUser(uidData.ltuid) + return `绑定cookie已删除` } /** 绑定uid,若有ck的话优先使用ck-uid */ @@ -236,57 +152,69 @@ export default class User extends base { if (!uid) return uid = uid[0] let user = await this.user() - await user.setRegUid(uid, true) - return await this.e.reply(`绑定成功uid:${uid}`, false, { at: true }) + await user.addRegUid(uid, this.e) + return await this.showUid() + } + + async delUid (index) { + let user = await this.user() + let game = this.e + let uidList = user.getUidList(game) + if (index > uidList.length) { + return await this.e.reply('uid序号输入错误') + } + index = Number(index) - 1 + let uidObj = uidList[index] + if (uidObj.type === 'ck') { + return await this.e.reply('CK对应UID无法直接删除,请通过【#删除ck】命令来删除') + } + await user.delRegUid(uidObj.uid, game) + return await this.showUid() } /** #uid */ async showUid () { let user = await this.user() - if (!user.hasCk) { - await this.e.reply(`当前绑定uid:${user.uid || '无'}`, false, { at: true }) - return - } - let uids = user.ckUids - let ckData = user.ckData - let uid = user.uid * 1 - let msg = [`当前uid:${uid}`, '当前绑定cookie Uid列表', '通过【#uid+序号】来切换uid'] - let region_name = [] - Object.keys(ckData).forEach((v) => { - if (!region_name.includes(ckData[v].region_name)) { - region_name.push(ckData[v].region_name) + let msg = [] + lodash.forEach({ gs: '原神', sr: '星穹铁道' }, (gameName, game) => { + let uidList = user.getUidList(game) + let currUid = user.getUid(game) + if (uidList.length === 0) { + return true } - }) - let count = 0 - for (let n of region_name) { - msg.push(n) - for (let i in uids) { - if (ckData[uids[i]].region_name == n) { - let tmp = `${++count}: ${uids[i]}` - if (uids[i] * 1 === uid) { - tmp += ' ☑' - } - msg.push(tmp) + msg.push(`【${gameName}】`) + lodash.forEach(uidList, (ds, idx) => { + let tmp = `${++idx}: ${ds.uid} (${ds.type})` + if (currUid * 1 === ds.uid * 1) { + tmp += ' ☑' } - } + msg.push(tmp) + }) + }) + if (msg.length > 0) { + msg.unshift('通过【#uid+序号】来切换uid') + await this.e.reply(msg.join('\n')) + } else { + await this.e.reply('尚未绑定UID,发送CK或通过【#绑定123456789】命令来绑定UID') } - await this.e.reply(msg.join('\n')) } /** 切换uid */ async toggleUid (index) { let user = await this.user() - let uidList = user.ckUids + let game = this.e + let uidList = user.getUidList(game) if (index > uidList.length) { return await this.e.reply('uid序号输入错误') } index = Number(index) - 1 - await user.setMainUid(index) - return await this.e.reply(`切换成功,当前uid:${user.uid}`) + user.setMainUid(index, game) + await user.save() + return await this.showUid() } - /** 加载旧ck */ - async loadOldData () { + /** 加载V2ck */ + async loadOldDataV2 () { let file = [ './data/MysCookie/NoteCookie.json', './data/NoteCookie/NoteCookie.json', @@ -324,33 +252,105 @@ export default class User extends base { qq, ck: ck.cookie, ltuid, - isMain, - device_id: this.getGuid() + isMain } }) - lodash.forEach(arr, (ck, qq) => { - let saveFile = `./data/MysCookie/${qq}.yaml` - if (fs.existsSync(saveFile)) return - gsCfg.saveBingCk(qq, ck) - }) - - logger.mark(logger.green(`加载用户ck完成:${lodash.size(arr)}个`)) - + let count = await this.loadOldData(arr) + if (count > 0) { + logger.mark(logger.green(`DB导入V2用户ck${count}个`)) + } fs.unlinkSync(json) } + /** 加载V3ck */ + async loadOldDataV3 (data) { + let dir = './data/MysCookie/' + Data.createDir('./data/MysCookieBak') + let files = fs.readdirSync(dir).filter(file => file.endsWith('.yaml')) + const readFile = promisify(fs.readFile) + let promises = [] + files.forEach((v) => promises.push(readFile(`${dir}${v}`, 'utf8'))) + const res = await Promise.all(promises) + let ret = {} + for (let v of res) { + v = YAML.parse(v) + let qq + for (let k in v) { + qq = qq || v[k]?.qq + } + if (qq) { + ret[qq] = v + } + } + let count = await this.loadOldData(ret) + if (count > 0) { + logger.mark(logger.green(`DB导入V3用户ck${count}个`)) + } + } + + async loadOldData (data) { + let count = 0 + if (!lodash.isPlainObject(data)) { + return + } + for (let u in data) { + let ltuids = {} + let v = data[u] + let qq + for (let k in v) { + let data = v[k] + qq = qq || data?.qq + let { uid, ck, ltuid, region_name: region, device_id: device } = data + ltuids[ltuid] = ltuids[ltuid] || { + ck, + device, + ltuid, + uids: {}, + type: /America Server|Europe Server|Asia Server/.test(region) ? 'hoyolab' : 'mys' + } + let tmp = ltuids[ltuid] + let game = region === '星穹列车' ? 'sr' : 'gs' + tmp.uids[game] = tmp.uids[game] || [] + let gameUids = tmp.uids[game] + if (!gameUids.includes(uid + '')) { + gameUids.push(uid + '') + } + } + if (!qq) { + continue + } + let user = await NoteUser.create(qq) + for (let ltuid in ltuids) { + let data = ltuids[ltuid] + let mys = await MysUser.create(data.ltuid) + if (mys) { + mys.setCkData(data) + await mys.save() + user.addMysUser(mys) + } + } + await user.save() + if (fs.existsSync(`./data/MysCookie/${qq}.yaml`)) { + fs.rename(`./data/MysCookie/${qq}.yaml`, `./data/MysCookieBak/${qq}.yaml`, (err) => { + if (err) console.log(err) + }) + } + count++ + } + return count + } + /** 我的ck */ async myCk () { let user = await this.user() if (!user.hasCk) { this.e.reply('当前尚未绑定cookie') } - let ck = user.mainCk - - if (!lodash.isEmpty(ck)) { - await this.e.reply(`当前绑定cookie\nuid:${ck.uid}`) - await this.e.reply(ck.ck) + let mys = user.getMysUser(this.e) + if (mys) { + await this.e.reply(`当前绑定cookie\nuid:${mys.getUid(this.e)}`) + await this.e.reply(mys.ck) } } @@ -386,14 +386,6 @@ export default class User extends base { await this.e.reply(cks.join('\n----\n'), false, { at: true }) } - getGuid () { - function S4 () { - return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1) - } - - return (S4() + S4() + '-' + S4() + '-' + S4() + '-' + S4() + '-' + S4() + S4() + S4()) - } - async userAdmin () { this.model = 'userAdmin' await MysInfo.initCache() From cb4a811e21043ce897198fe4cd7eff29fc485aae Mon Sep 17 00:00:00 2001 From: Qielanyinyin <75341397+Qielanyinyin@users.noreply.github.com> Date: Sun, 28 May 2023 04:49:03 +0800 Subject: [PATCH 28/33] =?UTF-8?q?3.7=E4=B8=8A=E5=8D=8A=E5=8D=A1=E6=B1=A0?= =?UTF-8?q?=E6=9B=B4=E6=96=B0=20(#135)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- plugins/genshin/defSet/gacha/pool.yaml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/plugins/genshin/defSet/gacha/pool.yaml b/plugins/genshin/defSet/gacha/pool.yaml index c5c87b8..016ddca 100644 --- a/plugins/genshin/defSet/gacha/pool.yaml +++ b/plugins/genshin/defSet/gacha/pool.yaml @@ -1,3 +1,21 @@ +- up4: + - 绮良良 + - 云堇 + - 重云 + up5: + - 宵宫 + up5_2: + - 八重神子 + weapon5: + - 飞雷之弦振 + - 神乐之真意 + weapon4: + - 恶王丸 + - 笛剑 + - 匣里灭辰 + - 流浪乐章 + - 弓藏 + endTime: "2023-06-13 18:00:00" - up4: - 卡维 - 坎蒂丝 From a499f1ca51b55d79e282fda2b00c524491d5e447 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A6=BB=E6=95=A3?= <101582156+LiSanSky@users.noreply.github.com> Date: Sun, 28 May 2023 04:49:37 +0800 Subject: [PATCH 29/33] Update README.md (#138) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 昨天安装发现这个安装依赖仍然会导致部分字体乱码,安装这个字体可以完美结局 --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index cb7259f..da11215 100644 --- a/README.md +++ b/README.md @@ -98,9 +98,9 @@ linux环境,其他环境请自行探索 ```sh yum install pango.x86_64 libXcomposite.x86_64 libXcursor.x86_64 libXdamage.x86_64 libXext.x86_64 libXi.x86_64 libXtst.x86_64 cups-libs.x86_64 libXScrnSaver.x86_64 libXrandr.x86_64 GConf2.x86_64 alsa-lib.x86_64 atk.x86_64 gtk3.x86_64 -y ``` -### 字体(实测下来貌似还不够) +### 乱码字体解决办法(centos,安装不了请换源) ```sh - yum install ipa-gothic-fonts xorg-x11-fonts-100dpi xorg-x11-fonts-75dpi xorg-x11-utils xorg-x11-fonts-cyrillic xorg-x11-fonts-Type1 xorg-x11-fonts-misc -y + yum groupinstall fonts -y ``` ## 致谢 From 109ff74a7ca9edc0b20fc9ac22512a7008da5128 Mon Sep 17 00:00:00 2001 From: liuzj288 Date: Sun, 28 May 2023 04:52:15 +0800 Subject: [PATCH 30/33] Update name.yaml (#139) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 增加绮良良角色id,以响应角色攻略 --- plugins/genshin/defSet/role/name.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/plugins/genshin/defSet/role/name.yaml b/plugins/genshin/defSet/role/name.yaml index 902e7bf..8a0e217 100644 --- a/plugins/genshin/defSet/role/name.yaml +++ b/plugins/genshin/defSet/role/name.yaml @@ -577,6 +577,10 @@ - 叶澜 - 腋兰 - 夜天后 +10000061: + - 绮良良 + - 草猫 + - 猫又 10000062: - 埃洛伊 - Aloy From ea5e451b30836b53c99ec41f9d72ce166cb58753 Mon Sep 17 00:00:00 2001 From: echo <109016927+zlh-debug@users.noreply.github.com> Date: Sun, 28 May 2023 04:52:44 +0800 Subject: [PATCH 31/33] #101 (#142) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: #101 * 修复祈愿分析链接错误问题 --- plugins/genshin/model/gachaLog.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/genshin/model/gachaLog.js b/plugins/genshin/model/gachaLog.js index c64e4a6..bc40136 100644 --- a/plugins/genshin/model/gachaLog.js +++ b/plugins/genshin/model/gachaLog.js @@ -82,7 +82,8 @@ export default class GachaLog extends base { dealUrl(url) { // timestamp=1641338980〈=zh-cn 修复链接有奇怪符号 - url = url.replace(/〈=/g, '&').split('getGachaLog?')[1] + url = url.replace(/〈=/g, '&') + if (url.includes("getGachaLog?")) url = url.split('getGachaLog?')[1] // 处理参数 let arr = new URLSearchParams(url).entries() From b5c2ab5330f176ae3600caa7ad7a4be1cce20ca3 Mon Sep 17 00:00:00 2001 From: Kokomi <102026640+yoimiya-kokomi@users.noreply.github.com> Date: Sun, 28 May 2023 05:30:19 +0800 Subject: [PATCH 32/33] =?UTF-8?q?v3.1.0=20=E6=94=AF=E6=8C=81=E5=A4=9AUID?= =?UTF-8?q?=E7=BB=91=E5=AE=9A=EF=BC=8C=E5=8F=AF=E7=BB=91=E5=AE=9A=E5=A4=9A?= =?UTF-8?q?=E4=B8=AAUID=E5=B9=B6=E8=BF=9B=E8=A1=8C=E5=88=87=E6=8D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 9 ++++++--- package.json | 2 +- plugins/genshin/model/db/BaseModel.js | 1 - plugins/genshin/model/mys/NoteUser.js | 5 ++++- plugins/genshin/model/user.js | 24 +++++++++++++----------- 5 files changed, 24 insertions(+), 17 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 30c3a71..f4931c7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,11 @@ -# 3.1.0 Dev +# 3.1.0 -* !!!暂未完成,会有很多错误,不建议升级!!! * 重构CK与UID管理逻辑 -* 底层对星铁查询进行支持 + * 支持多UID绑定,可绑定多个UID并进行切换 + * 支持原神与星铁UID共存,可针对查询命令分配对应UID + * 新增`#删除uid1`命令,可对`#uid`列表内的绑定UID进行删除 + * 使用sqlite进行ck与uid存储 +* 底层对星铁查询进行支持 **@cvs** # 3.0.2 diff --git a/package.json b/package.json index 27ccf89..bf21ef4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "miao-yunzai", - "version": "3.0.2", + "version": "3.1.0", "author": "Yoimiya-Kokomi, Le-niao", "description": "QQ group Bot", "main": "app.js", diff --git a/plugins/genshin/model/db/BaseModel.js b/plugins/genshin/model/db/BaseModel.js index 45863cb..1dfe33d 100644 --- a/plugins/genshin/model/db/BaseModel.js +++ b/plugins/genshin/model/db/BaseModel.js @@ -18,7 +18,6 @@ export default class BaseModel extends Model { static initDB (model, columns) { let name = model.name - console.log('Model Name', name) name = name.replace(/DB$/, 's') model.init(columns, { sequelize, tableName: name }) model.COLUMNS = columns diff --git a/plugins/genshin/model/mys/NoteUser.js b/plugins/genshin/model/mys/NoteUser.js index 9e62201..3efed5e 100644 --- a/plugins/genshin/model/mys/NoteUser.js +++ b/plugins/genshin/model/mys/NoteUser.js @@ -262,9 +262,12 @@ export default class NoteUser extends BaseModel { if (this.uidMap[gameKey][uid] && this.uidMap[gameKey][uid].type !== 'ck') { lodash.remove(this.uidList[gameKey], (u) => u + '' === uid + '') delete this.uidMap[gameKey][uid] + if (this.mainUid[gameKey] === uid) { + this.mainUid[gameKey] = '' + } } await this.save() - if (this.mainUid[gameKey] === uid) { + if (this.mainUid[gameKey] === '') { this.setMainUid(this.uidList[gameKey][0], game) await this.save() } diff --git a/plugins/genshin/model/user.js b/plugins/genshin/model/user.js index 9750a06..a50e0bb 100644 --- a/plugins/genshin/model/user.js +++ b/plugins/genshin/model/user.js @@ -176,27 +176,25 @@ export default class User extends base { async showUid () { let user = await this.user() let msg = [] - lodash.forEach({ gs: '原神', sr: '星穹铁道' }, (gameName, game) => { + let typeMap = { ck: 'CK Uid', reg: '绑定uid' } + lodash.forEach({ gs: '原神 (#uid)', sr: '星穹铁道 (*uid)' }, (gameName, game) => { let uidList = user.getUidList(game) let currUid = user.getUid(game) + msg.push(`【${gameName}】`) if (uidList.length === 0) { + msg.push(`暂无,通过${game === 'gs' ? '#' : '*'}绑定123456789来绑定UID`) return true } - msg.push(`【${gameName}】`) lodash.forEach(uidList, (ds, idx) => { - let tmp = `${++idx}: ${ds.uid} (${ds.type})` + let tmp = `${++idx}: ${ds.uid} (${typeMap[ds.type]})` if (currUid * 1 === ds.uid * 1) { tmp += ' ☑' } msg.push(tmp) }) }) - if (msg.length > 0) { - msg.unshift('通过【#uid+序号】来切换uid') - await this.e.reply(msg.join('\n')) - } else { - await this.e.reply('尚未绑定UID,发送CK或通过【#绑定123456789】命令来绑定UID') - } + msg.unshift('通过【#uid+序号】来切换uid,【#删除uid+序号】删除uid') + await this.e.reply(msg.join('\n')) } /** 切换uid */ @@ -266,10 +264,14 @@ export default class User extends base { /** 加载V3ck */ async loadOldDataV3 (data) { let dir = './data/MysCookie/' - Data.createDir('./data/MysCookieBak') + Data.createDir('./temp/MysCookieBak') let files = fs.readdirSync(dir).filter(file => file.endsWith('.yaml')) const readFile = promisify(fs.readFile) let promises = [] + if (files.length === 0) { + fs.rmdirSync('./data/MysCookie/') + return + } files.forEach((v) => promises.push(readFile(`${dir}${v}`, 'utf8'))) const res = await Promise.all(promises) let ret = {} @@ -332,7 +334,7 @@ export default class User extends base { } await user.save() if (fs.existsSync(`./data/MysCookie/${qq}.yaml`)) { - fs.rename(`./data/MysCookie/${qq}.yaml`, `./data/MysCookieBak/${qq}.yaml`, (err) => { + fs.rename(`./data/MysCookie/${qq}.yaml`, `./temp/MysCookieBak/${qq}.yaml`, (err) => { if (err) console.log(err) }) } From fa5fe1338cff2e50c088c29d8bd49a3a5bc31329 Mon Sep 17 00:00:00 2001 From: Kokomi <102026640+yoimiya-kokomi@users.noreply.github.com> Date: Sun, 28 May 2023 05:51:13 +0800 Subject: [PATCH 33/33] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E9=83=A8=E5=88=86READM?= =?UTF-8?q?E=E8=AF=B4=E6=98=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 36 ++++++++++++++++++++++------------- plugins/genshin/model/user.js | 2 +- 2 files changed, 24 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index da11215..0b93865 100644 --- a/README.md +++ b/README.md @@ -4,23 +4,27 @@ 需要同时安装[miao-plugin](https://github.com/yoimiya-kokomi/miao-plugin.git) ,且后续的一些底层改造可能会改变数据结构,无法直接迁回原版Yunzai,请根据自己需求情况慎重安装 +使用[icqq](https://github.com/icqqjs/icqq) 登录,防止oicq可能出现的低版本问题 + --- +与原版Yunzai-Bot的差异: -与原Yunzai独立的仓库,去除了较为敏感的签到功能,以尝试恢复[Github](https://github.com/yoimiya-kokomi/Miao-Yunzai.git) -环境。附加[Gitee](https://gitee.com/yoimiya-kokomi/Miao-Yunzai.git) +**【注意】:** 由于是独立新的仓库,【只建议新部署/部署后迁移】,不建议原Bot直接换源强更 -* 由于是独立新的仓库,【只建议新部署/部署后迁移】,不建议原Bot直接换源强更 -* 使用icqq登录,防止oicq可能出现的低版本问题(如只需要此特性,可使用[Yunzai-V3](https://gitee.com/yoimiya-kokomi/Yunzai-Bot) ) -* 基础功能会保持与Yunzai同步迭代更新,如只需原版Yunzai功能则无需切换 +* **一些新特性:** Miao-Yunzai会逐步重构,增加新特性与功能,可能会有功能与形态上的变化。如期望功能更加稳定可使用此仓库[Yunzai-V3](https://gitee.com/yoimiya-kokomi/Yunzai-Bot) +* **移除了签到功能:** 与原Yunzai独立的仓库,去除了较为敏感的签到功能,以尝试恢复[Github](https://github.com/yoimiya-kokomi/Miao-Yunzai.git) + 环境。附加[Gitee](https://gitee.com/yoimiya-kokomi/Miao-Yunzai.git) +* **默认启用喵版的功能:** 【#角色】【#深渊】【#帮助】等功能默认启用喵版,原版的逻辑会屏蔽,以便于后续逐步精简资源 ## Miao-Yunzai后续计划 先刨坑,但也许会咕咕咕 * 功能与`miao-plugin`部分功能进行整合或升级 - * 角色卡片、抽卡分析等使用`miao-plugin`版本 + * [√] 角色卡片、抽卡分析等使用`miao-plugin`版本 * `miao-plugin`的帮助、设置、版本信息会升至`Miao-Yunzai`,以支持更多场景 * 一些底层会与`miao-plugin`做更深层的联动,以支持一些高级功能 + * [√] 星铁底层支持,原神&星铁多UID支持 * 基于面板信息的uid管理及认证 * ck切换感知等 * 逐步实验一些新的特性 @@ -77,7 +81,6 @@ pnpm install -P node app ``` - ## 常见问题 ### puppeteer 相关问题 @@ -88,26 +91,33 @@ linux环境,其他环境请自行探索 puppeteer Chromium 启动中... Error: Failed to launch the browser process! ``` + 1. 先检查node版本是否大于14 (不大于14请去升级版本) + ```sh node -v ``` + 2. 如果大于14 则可能是缺失一些库 请安装这些 (点击代码块右上角直接复制,如果报错可以尝试 sudo) ### 依赖库 + ```sh yum install pango.x86_64 libXcomposite.x86_64 libXcursor.x86_64 libXdamage.x86_64 libXext.x86_64 libXi.x86_64 libXtst.x86_64 cups-libs.x86_64 libXScrnSaver.x86_64 libXrandr.x86_64 GConf2.x86_64 alsa-lib.x86_64 atk.x86_64 gtk3.x86_64 -y ``` + ### 乱码字体解决办法(centos,安装不了请换源) + ```sh yum groupinstall fonts -y ``` ## 致谢 -| Nickname | Contribution | -|:-------------------------------------------------------------:|-------------------| -| [Yunzai v3.0](https://gitee.com/le-niao/Yunzai-Bot) | 乐神的Yunzai-Bot V3 | -| [GardenHamster](https://github.com/GardenHamster/GenshinPray) | 模拟抽卡背景素材来源 | -| [西风驿站](https://bbs.mihoyo.com/ys/collection/839181) | 角色攻略图来源 | -| [米游社友人A](https://bbs.mihoyo.com/ys/collection/428421) | 角色突破素材图来源 | +| Nickname | Contribution | +|:-------------------------------------------------------------:|------------------| +| [Yunzai v3.0](https://gitee.com/le-niao/Yunzai-Bot) | 乐神的Yunzai-Bot V3 | +| [GardenHamster](https://github.com/GardenHamster/GenshinPray) | 模拟抽卡背景素材来源 | +| [西风驿站](https://bbs.mihoyo.com/ys/collection/839181) | 角色攻略图来源 | +| [米游社友人A](https://bbs.mihoyo.com/ys/collection/428421) | 角色突破素材图来源 | +| [icqq](https://github.com/icqqjs/icqq) | ICQQ | diff --git a/plugins/genshin/model/user.js b/plugins/genshin/model/user.js index a50e0bb..8888b08 100644 --- a/plugins/genshin/model/user.js +++ b/plugins/genshin/model/user.js @@ -176,7 +176,7 @@ export default class User extends base { async showUid () { let user = await this.user() let msg = [] - let typeMap = { ck: 'CK Uid', reg: '绑定uid' } + let typeMap = { ck: 'CK Uid', reg: '绑定 Uid' } lodash.forEach({ gs: '原神 (#uid)', sr: '星穹铁道 (*uid)' }, (gameName, game) => { let uidList = user.getUidList(game) let currUid = user.getUid(game)