From a76b7d98a913431f8352f1d2250678f7fd835993 Mon Sep 17 00:00:00 2001 From: Kokomi <102026640+yoimiya-kokomi@users.noreply.github.com> Date: Fri, 10 Feb 2023 00:57:25 +0800 Subject: [PATCH] =?UTF-8?q?=E9=9D=A2=E6=9D=BF=E6=95=B0=E6=8D=AE=E7=BB=93?= =?UTF-8?q?=E6=9E=84=E5=8F=98=E6=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/character/AvatarCard.js | 4 +- apps/profile/ProfileCommon.js | 27 ++- apps/profile/ProfileDetail.js | 6 +- apps/profile/ProfileList.js | 1 - apps/profile/ProfileRank.js | 2 +- models/Avatar.js | 210 ---------------- models/AvatarArtis.js | 4 +- models/AvatarData.js | 54 +++-- models/AvatarList.js | 135 ----------- models/Player.js | 93 ++----- models/ProfileArtis.js | 191 +-------------- models/ProfileData.js | 130 ++-------- models/ProfileReq.js | 39 ++- models/ProfileServ.js | 11 - models/index.js | 4 - models/player-lib/{enka.js => EnkaApi.js} | 20 +- models/player-lib/EnkaData.js | 105 ++++++++ models/player-lib/{miao.js => MiaoApi.js} | 7 +- .../player-lib/{miao-data.js => MiaoData.js} | 132 ++++------ models/player-lib/Profile.js | 60 +++++ .../{enka-meta.js => ProfileMeta.js} | 39 ++- models/player-lib/enka-data.js | 227 ------------------ models/profile-lib/AttrCalc.js | 3 - resources/character/profile-detail.html | 2 +- 24 files changed, 379 insertions(+), 1127 deletions(-) delete mode 100644 models/Avatar.js delete mode 100644 models/AvatarList.js rename models/player-lib/{enka.js => EnkaApi.js} (76%) create mode 100644 models/player-lib/EnkaData.js rename models/player-lib/{miao.js => MiaoApi.js} (89%) rename models/player-lib/{miao-data.js => MiaoData.js} (65%) create mode 100644 models/player-lib/Profile.js rename models/player-lib/{enka-meta.js => ProfileMeta.js} (95%) delete mode 100644 models/player-lib/enka-data.js diff --git a/apps/character/AvatarCard.js b/apps/character/AvatarCard.js index 0534a647..a5b1d5ff 100644 --- a/apps/character/AvatarCard.js +++ b/apps/character/AvatarCard.js @@ -1,4 +1,4 @@ -import { Character, Avatar, MysApi, Player } from '../../models/index.js' +import { Character, MysApi, Player } from '../../models/index.js' import { Cfg, Common } from '../../components/index.js' import lodash from 'lodash' import { segment } from 'oicq' @@ -6,7 +6,6 @@ import moment from 'moment' export async function renderAvatar (e, avatar, renderType = 'card') { // 如果传递的是名字,则获取 - let uid = e.uid if (typeof (avatar) === 'string') { // 检查角色 let char = Character.get(avatar) @@ -15,7 +14,6 @@ export async function renderAvatar (e, avatar, renderType = 'card') { } let mys = await MysApi.init(e) if (!mys) return true - uid = mys.uid if (!char.isRelease) { avatar = { id: char.id, name: char.name, detail: false } } else { diff --git a/apps/profile/ProfileCommon.js b/apps/profile/ProfileCommon.js index e53dd35c..6a80f372 100644 --- a/apps/profile/ProfileCommon.js +++ b/apps/profile/ProfileCommon.js @@ -10,7 +10,7 @@ import { Character, MysApi, Player } from '../../models/index.js' /* * 获取面板查询的 目标uid * */ -export async function getTargetUid (e) { +const _getTargetUid = async function (e) { let uidReg = /[1-9][0-9]{8}/ if (e.uid && uidReg.test(e.uid)) { @@ -67,6 +67,14 @@ export async function getTargetUid (e) { return uid || false } +export async function getTargetUid (e) { + let uid = await _getTargetUid(e) + if (uid) { + e.uid = uid + } + return uid +} + /* * 自动更新面板数据 * */ @@ -87,8 +95,8 @@ export async function autoRefresh (e) { e.isRefreshed = true // 数据更新 - let player = Player.create(uid) - let data = await player.refreshProfile(e) + let player = Player.create(e) + let data = await player.refreshProfile() if (!data) { return false } @@ -128,7 +136,8 @@ export async function autoGetProfile (e, uid, avatar, callback) { return { err: true } } - let profile = Player.getAvatar(uid, char.id) + let player = Player.create(e) + let profile = player.getProfile(char.id) if (!profile || !profile.hasData) { if (await refresh()) { return { err: true } @@ -136,13 +145,7 @@ export async function autoGetProfile (e, uid, avatar, callback) { e.reply(`请确认${char.name}已展示在【游戏内】的角色展柜中,并打开了“显示角色详情”。然后请使用 #更新面板\n命令来获取${char.name}的面板详情`) } return { err: true } - } else if (!['enka', 'miao'].includes(profile.dataSource)) { - if (!await refresh()) { - e.reply('缓存数据错误,请重新获取面板信息后查看') - } - return { err: true } } - return { profile, char, refresh } } @@ -156,8 +159,8 @@ export async function getProfile (e) { } // 数据更新 - let player = Player.create(uid) - let ret = await player.refreshProfile(e) + let player = Player.create(e) + let ret = await player.refreshProfile() if (!ret) { return true } diff --git a/apps/profile/ProfileDetail.js b/apps/profile/ProfileDetail.js index c1877e06..097f48b8 100644 --- a/apps/profile/ProfileDetail.js +++ b/apps/profile/ProfileDetail.js @@ -1,7 +1,7 @@ import lodash from 'lodash' import { autoRefresh } from './ProfileCommon.js' import { Common, Format } from '../../components/index.js' -import { MysApi, Avatar, ProfileRank, ProfileArtis, Player } from '../../models/index.js' +import { MysApi, ProfileRank, ProfileArtis, Player } from '../../models/index.js' export async function renderProfile (e, char, mode = 'profile', params = {}) { let selfUser = await MysApi.initUser(e) @@ -19,7 +19,8 @@ export async function renderProfile (e, char, mode = 'profile', params = {}) { } let player = Player.create(uid) - let profile = e._profile || player.getProfile(char.id) + let avatar = player.getAvatar(char.id) + let profile = e._profile || avatar.getProfile(char.id) let refresh = async () => { let refreshRet = await autoRefresh(e) @@ -37,7 +38,6 @@ export async function renderProfile (e, char, mode = 'profile', params = {}) { } return true } - let avatar = new Avatar(profile) char = profile.char || char let a = profile.attr let c = Format.comma diff --git a/apps/profile/ProfileList.js b/apps/profile/ProfileList.js index 64fa0fb9..8f1f4e42 100644 --- a/apps/profile/ProfileList.js +++ b/apps/profile/ProfileList.js @@ -47,7 +47,6 @@ export async function profileList (e) { let char = profile.char let tmp = char.getData('id,face,name,abbr,element,star') tmp.face = char.getImgs(profile.costume).face - tmp.source = profile.dataSource tmp.level = profile.level || 1 tmp.cons = profile.cons tmp.isNew = 0 diff --git a/apps/profile/ProfileRank.js b/apps/profile/ProfileRank.js index 4efe0700..89ed073b 100644 --- a/apps/profile/ProfileRank.js +++ b/apps/profile/ProfileRank.js @@ -1,4 +1,4 @@ -import { Character, ProfileRank, ProfileDmg, Avatar, Player } from '../../models/index.js' +import { Character, ProfileRank, ProfileDmg, Player } from '../../models/index.js' import { renderProfile } from './ProfileDetail.js' import { Data, Common, Format } from '../../components/index.js' import lodash from 'lodash' diff --git a/models/Avatar.js b/models/Avatar.js deleted file mode 100644 index 9e4e245b..00000000 --- a/models/Avatar.js +++ /dev/null @@ -1,210 +0,0 @@ -/* -* 用户角色封装 -* 兼容处理面板 Profile Data 及 Mys Avatar 数据 -* */ -import Base from './Base.js' -import lodash from 'lodash' -import { Artifact, Character, Weapon, ArtifactSet, Player } from './index.js' -import moment from 'moment' - -const charKey = 'name,abbr,sName,star,imgs,face,side,gacha,weaponTypeName,elem'.split(',') - -export default class Avatar extends Base { - constructor (data = {}, pd = false, hasCk = true) { - super() - if (!data.name) { - return false - } - let char = Character.get(data.name) - if (!char || char.isCustom) { - return false - } - this.meta = data - this.char = char - let isProfile = data.isProfile - this.dataType = isProfile ? 'profile' : 'avatar' - this.hasCk = hasCk - let profile - let uid - if (isProfile) { - profile = data - } else if (pd) { - if (pd.isProfile) { - profile = pd - } else if (/\d{9}/.test(pd)) { - uid = pd - profile = Player.getAvatar(pd, char.id, true) - } - } - if (profile && profile.isProfile && profile.hasData) { - this.profile = profile - } - this.elem = ((profile && profile.elem) || data.element || data.elem || char.elem || 'anemo').toLowerCase() - if (char.isTraveler) { - this.char = Character.get({ id: data.id || char.id, elem: this.elem }) - uid && char.setTraveler(uid) - } - } - - _get (key) { - if (charKey.includes(key)) { - return this.char[key] - } - return this.meta[key] - } - - get dataSourceName () { - if (!this.hasCk && this.profile) { - return this.profile.dataSourceName - } - return this.meta.dataSourceName || '米游社' - } - - get updateTime () { - if ((!this.hasCk || this.isProfile) && this.profile) { - return this.profile.updateTime - } - return moment(new Date()).format('MM-DD HH:mm') - } - - get isProfile () { - return this.dataType === 'profile' - } - - get isAvatar () { - return this.dataType === 'avatar' - } - - get artis () { - let ret = {} - if (!this.isProfile) { - lodash.forEach(this.meta.reliquaries, (ds) => { - let arti = Artifact.get(ds.name) - ret[arti.idx] = { - name: arti.name, - set: arti.setName, - img: arti.img, - level: ds.level - } - }) - return ret - } - if (this.profile && this.profile?.artis) { - return this.profile.artis.getArtisData() - } - return false - } - - get cons () { - let data = this.meta - let profile = this.profile - return data?.cons || data?.actived_constellation_num || profile?.cons || 0 - } - - get weapon () { - let wd = this.meta?.weapon || this.profile?.weapon - if (!wd || !wd.name) { - return {} - } - let weapon = Weapon.get(wd.name) - return { - name: wd.name, - abbr: weapon.abbr, - star: weapon.star, - level: wd.level || 1, - affix: wd.affix || wd.affix_level || 0, - type: weapon.type, - img: weapon.img - } - } - - async getTalent (mys) { - if (!this.isProfile && mys && mys.isSelfCookie) { - let char = this.char - let id = char.id - let talent = {} - let talentRes = await mys.getDetail(id) - // { data: null, message: '请先登录', retcode: -100, api: 'detail' } - let avatar = this.meta - if (!char || !avatar) { - return false - } - if (talentRes && talentRes.skill_list) { - let talentList = lodash.orderBy(talentRes.skill_list, ['id'], ['asc']) - for (let val of talentList) { - let { max_level: maxLv, level_current: lv } = val - if (val.name.includes('普通攻击')) { - talent.a = lv - continue - } - if (maxLv >= 10 && !talent.e) { - talent.e = lv - continue - } - if (maxLv >= 10 && !talent.q) { - talent.q = lv - continue - } - } - } - let ret = char.getAvatarTalent(talent, this.cons, 'original') - if (ret) { - ret.id = id - } - return ret - } - if (this.profile) { - let profile = this.profile - let talent = profile.talent - talent.id = profile.id - return talent - } - return false - } - - get artisSet () { - if (this._artisSet) { - return this._artisSet - } - this._artisSet = false - if (!this.isProfile) { - let artis = this.artis - let setCount = {} - lodash.forEach(artis, (arti, idx) => { - let set = arti?.set - if (set) { - setCount[set] = (setCount[set] || 0) + 1 - } - }) - let sets = {} - let names = [] - let abbrs = [] - let abbrs2 = [] - let imgs = [] - for (let set in setCount) { - if (setCount[set] >= 2) { - let value = setCount[set] >= 4 ? 4 : 2 - sets[set] = value - let artiSet = ArtifactSet.get(set) - names.push(artiSet.name) - abbrs.push(artiSet.abbr + value) - abbrs2.push(artiSet.name + value) - imgs.push(artiSet.img) - } - } - this._artisSet = { - sets, - names, - abbrs: [...abbrs, ...abbrs2], - imgs, - name: (abbrs.length > 1 || abbrs2[0]?.length > 7) ? abbrs.join('+') : abbrs2[0], - sName: abbrs.join('+') - } - } - if (this.profile) { - let profile = this.profile - this._artisSet = profile.artis ? profile.artis.getSetData() : false - } - return this._artisSet || {} - } -} \ No newline at end of file diff --git a/models/AvatarArtis.js b/models/AvatarArtis.js index a335cdd2..2293f7d5 100644 --- a/models/AvatarArtis.js +++ b/models/AvatarArtis.js @@ -27,7 +27,7 @@ export default class AvatarArtis extends Base { return ret } - setArtisData (ds = {}, dataSource) { + setArtisData (ds = {}, source) { if (!this.hasArtis || AvatarArtis.isProfileArtis(ds) || !AvatarArtis.isProfileArtis(this.artis)) { for (let idx = 1; idx <= 5; idx++) { if (ds[idx]) { @@ -204,7 +204,7 @@ export default class AvatarArtis extends Base { * name: '组合名字', 若为4件套会使用套装完整名 * sName: '简写名字',若为4件套也会使用简写 */ - geSetData () { + getSetData () { let setCount = {} this.forEach((arti, idx) => { setCount[arti.set] = (setCount[arti.set] || 0) + 1 diff --git a/models/AvatarData.js b/models/AvatarData.js index 994c4ba3..ad049632 100644 --- a/models/AvatarData.js +++ b/models/AvatarData.js @@ -8,19 +8,23 @@ import AttrCalc from './profile-lib/AttrCalc.js' const charKey = 'name,abbr,sName,star,imgs,face,side,gacha,weaponTypeName'.split(',') export default class AvatarData extends Base { - constructor (ds = {}, dataSource) { + constructor (ds = {}, source) { super() let char = Character.get({ id: ds.id, elem: ds.elem }) if (!char) { - return false + return } this.id = char.id this.char = char - this.artis = new AvatarArtis(this.id) - this.setAvatar(ds, dataSource) + this.initArtis() + this.setAvatar(ds, source) } - static create (ds, dataSource) { + initArtis () { + this.artis = new AvatarArtis(this.id) + } + + static create (ds, source) { let avatar = new AvatarData(ds) if (!avatar) { return false @@ -38,7 +42,7 @@ export default class AvatarData extends Base { this._now = new Date() * 1 this.setBasic(ds, source) ds.weapon && this.setWeapon(ds.weapon) - ds.talent && this.setTalent(ds.talent, source) + ds.talent && this.setTalent(ds.talent, 'original', source) ds.artis && this.setArtis(ds) delete this._now } @@ -88,7 +92,7 @@ export default class AvatarData extends Base { } } - setTalent (ds = {}, source = '', mode = 'original') { + setTalent (ds = {}, mode = 'original', source = '') { const now = this._now || (new Date()) * 1 let ret = this.char.getAvatarTalent(ds, this.cons, mode) this.talent = ret || this.talent @@ -141,7 +145,7 @@ export default class AvatarData extends Base { } let ret = char.getAvatarTalent(talent, this.cons, 'original') if (ret) { - this.setTalent(ret, 'mys') + this.setTalent(ret, 'original', 'mys') } return true } @@ -188,7 +192,7 @@ export default class AvatarData extends Base { // 判断当前profileData是否具备有效圣遗物信息 hasArtis () { - return this.hasData && this.artis.length > 0 + return this.isProfile && this.artis.length > 0 } get costume () { @@ -216,6 +220,26 @@ export default class AvatarData extends Base { return this.getData(keys || 'id,name,level,star,cons,fetter,elem,face,side,gacha,abbr,weapon,talent,artisSet') || {} } + /** + * 获取圣遗物套装属性 + * @returns {boolean|*|{imgs: *[], names: *[], sets: {}, abbrs: *[], sName: string, name: (string|*)}|{}} + */ + get artisSet () { + return this.artis.getSetData() + } + + getArtisDetail () { + return this.artis.getDetail() + } + + get dataSource () { + return { + enka: 'Enka.Network', + miao: '喵喵Api', + mys: '米游社' + }[this._source] || this._source + } + get updateTime () { let time = this._time if (!time) { @@ -229,16 +253,4 @@ export default class AvatarData extends Base { } return '' } - - /** - * 获取圣遗物套装属性 - * @returns {boolean|*|{imgs: *[], names: *[], sets: {}, abbrs: *[], sName: string, name: (string|*)}|{}} - */ - get artisSet () { - return this.artis.geSetData() - } - - getArtisDetail () { - return this.artis.getDetail() - } } diff --git a/models/AvatarList.js b/models/AvatarList.js deleted file mode 100644 index 04c710a0..00000000 --- a/models/AvatarList.js +++ /dev/null @@ -1,135 +0,0 @@ -/* -* 用户角色列表 -* -* 批量管理及天赋等数据获取 -* 使用 Avatar Model实现兼容处理面板数据及Mys角色数据 -* */ -import Base from './Base.js' -import lodash from 'lodash' -import { Data, Common } from '../components/index.js' -import { Avatar, MysApi, Player } from './index.js' - -export default class AvatarList extends Base { - constructor (uid, datas = [], withProfile = false) { - super() - if (!uid) { - return false - } - this.uid = uid - let avatars = {} - let profiles = {} - let player = Player.create(uid) - if (withProfile) { - // TODO - } - lodash.forEach(datas, (ds) => { - let avatar = new Avatar(ds, profiles[ds.id] || false) - if (avatar) { - avatars[avatar.id] = avatar - } - }) - // 使用面板数据补全 - lodash.forEach(profiles, (profile) => { - if (!avatars[profile.id]) { - let avatar = new Avatar(profile) - if (avatar) { - avatars[avatar.id] = avatar - } - } - }) - this.avatars = avatars - } - - getData (ids, keys = '') { - let rets = {} - keys = keys || 'id,name,level,star,cons,fetter,elem,face,side,gacha,abbr,weapon,artisSet' - let avatars = this.avatars - lodash.forEach(ids, (id) => { - rets[id] = avatars[id].getData(keys) || {} - }) - return rets - } - - getAvatar (id) { - return this.avatars[id] - } - - getProfile (id) { - return this.avatars[id]?.profile - } - - getIds () { - let rets = [] - lodash.forEach(this.avatars, (ds) => { - rets.push(ds.id) - }) - return rets - } - - async getTalentData (ids = '', mys = false, keys = '') { - if (!ids) { - ids = this.getIds() - } - mys = mys || this._mys - let avatarTalent = await Data.getCacheJSON(`miao:avatar-talent:${this.uid}`) - let needReq = {} - lodash.forEach(ids, (id) => { - if (!avatarTalent[id] || !avatarTalent[id]?.a) { - needReq[id] = true - } - }) - let avatars = this.avatars - let needReqIds = lodash.keys(needReq) - if (needReqIds.length > 0) { - if (needReqIds.length > 8) { - this.e && this.e.reply('正在获取角色信息,请稍候...') - } - let num = 10 - let ms = 100 - let skillRet = [] - let avatarArr = lodash.chunk(needReqIds, num) - for (let val of avatarArr) { - for (let id of val) { - let avatar = avatars[id] - skillRet.push(await avatar.getTalent(mys)) - } - skillRet = await Promise.all(skillRet) - skillRet = skillRet.filter(item => item.id) - await Common.sleep(ms) - } - lodash.forEach(skillRet, (talent) => { - avatarTalent[talent.id] = talent - }) - await Data.setCacheJSON(`miao:avatar-talent:${this.uid}`, avatarTalent, 3600 * 2) - } - let ret = this.getData(ids, keys) - lodash.forEach(ret, (avatar, id) => { - avatar.talent = avatarTalent[id] || {} - }) - return ret - } - - get isSelfCookie () { - return !!this._mys?.isSelfCookie - } -} - -AvatarList.hasTalentCache = async function (uid) { - return !!await redis.get(`miao:avatar-talent:${uid}`) -} - -AvatarList.getAll = async function (e, mys = false) { - if (!mys) { - mys = await MysApi.init(e) - } - if (!mys || !mys.uid) return false - let uid = mys.uid - let data = await mys.getCharacter() - if (!data) { - return false - } - let ret = new AvatarList(uid, data.avatars, true) - ret.e = e - ret._mys = mys - return ret -} diff --git a/models/Player.js b/models/Player.js index 8189423a..54e6ce86 100644 --- a/models/Player.js +++ b/models/Player.js @@ -1,24 +1,20 @@ /** * 用户数据文件 */ +import lodash from 'lodash' import Base from './Base.js' import { Data } from '../components/index.js' -import fs from 'fs' -import { ProfileReq, AvatarData } from './index.js' -import Profile from './player-lib/profile.js' -import lodash from 'lodash' +import { AvatarData } from './index.js' import MysAvatar from './player-lib/MysAvatar.js' +import Profile from './player-lib/Profile.js' -const _path = process.cwd() -const userPath = `${_path}/data/UserData/` -if (!fs.existsSync(userPath)) { - fs.mkdirSync(userPath) -} +Data.createDir('/data/userData', 'root') export default class Player extends Base { constructor (uid) { super() + uid = uid?._mys?.uid || uid?.uid || uid if (!uid) { return false } @@ -32,9 +28,9 @@ export default class Player extends Base { } static create (e) { - if (e?._mys?.uid) { + if (e?._mys?.uid || e.uid) { // 传入为e - let player = new Player(e?._mys?.uid) + let player = new Player(e?._mys?.uid || e.uid) player.e = e return player } else { @@ -87,31 +83,20 @@ export default class Player extends Base { this._mys = ds._mys || this._mys } - /** - * 设置角色列表 - * @param ds - */ + // 设置角色列表 setAvatars (ds) { lodash.forEach(ds, (avatar) => { this.setAvatar(avatar) }) } - /** - * 设置角色 - * @param ds - * @param dataSource - */ - setAvatar (ds, source) { + // 设置角色数据 + setAvatar (ds, source = '') { let avatar = this.getAvatar(ds.id) avatar.setAvatar(ds, source) } - /** - * 获取角色 - * @param id - * @returns {*} - */ + // 获取Avatar角色 getAvatar (id) { if (!this._avatars[id]) { this._avatars[id] = AvatarData.create({ id }) @@ -119,11 +104,7 @@ export default class Player extends Base { return this._avatars[id] } - /** - * 循环角色 - * @param fn - * @returns {Promise} - */ + // 异步循环角色 async forEachAvatarAsync (fn) { for (let id in this._avatars) { let ret = await fn(this._avatars[id], id) @@ -133,6 +114,7 @@ export default class Player extends Base { } } + // 循环Avatar forEachAvatar (fn) { for (let id in this._avatars) { let ret = fn(this._avatars[id], id) @@ -142,6 +124,7 @@ export default class Player extends Base { } } + // 获取所有Avatar数据 getAvatarData (ids = '') { let ret = {} if (!ids) { @@ -156,20 +139,13 @@ export default class Player extends Base { return ret } - /** - * 获取当前用户指定charid面板数据 - * @param id - * @returns {*} - */ + // 获取指定角色的面板数据 getProfile (id) { let avatar = this.getAvatar(id) return avatar.getProfile() } - /** - * 获取当前用户所有面板数据 - * @returns {{}} - */ + // 获取所有面板数据 getProfiles () { let ret = {} lodash.forEach(this._avatars, (avatar) => { @@ -181,28 +157,9 @@ export default class Player extends Base { return ret } - /** - * 更新面板 - * @param e - * @returns {Promise} - */ - async refreshProfile (e, force = true) { - this._update = [] - let { uid } = this - if (uid.toString().length !== 9) { - return false - } - let req = new ProfileReq({ e, uid }) - try { - await req.request(this) - this._profile = new Date() * 1 - this.save() - return this._update.length - } catch (err) { - console.log(err) - e.reply('请求失败') - return false - } + // 更新面板 + async refreshProfile (force = true) { + return await Profile.refreshProfile(this, force) } // 更新米游社数据 @@ -220,17 +177,9 @@ export default class Player extends Base { return await MysAvatar.refreshTalent(this, ids, force) } - /** - * 获取面板更新服务名 - * @param uid - * @returns {*} - */ + // 获取面板更新服务名 static getProfileServName (uid) { - let Serv = ProfileReq.getServ(uid) + let Serv = Profile.getServ(uid) return Serv.name } - - static getAvatar (uid, charId, onlyHasData = false) { - return Profile.get(uid, charId, onlyHasData) - } } diff --git a/models/ProfileArtis.js b/models/ProfileArtis.js index 2ae832a3..7cf00fa6 100644 --- a/models/ProfileArtis.js +++ b/models/ProfileArtis.js @@ -2,187 +2,26 @@ * 面板圣遗物 */ import lodash from 'lodash' -import Base from './Base.js' +import AvatarArtis from './AvatarArtis.js' import { Artifact, ArtifactSet, Character } from './index.js' -import { Format, Data } from '../components/index.js' +import { Format } from '../components/index.js' import ArtisMark from './profile-lib/ArtisMark.js' import { attrMap, attrValue } from '../resources/meta/artifact/index.js' import CharArtis from './profile-lib/CharArtis.js' -export default class ProfileArtis extends Base { +export default class ProfileArtis extends AvatarArtis { constructor (charid = 0, elem = '') { - super() - this.charid = charid + super(charid) this.elem = elem - this.artis = {} } setProfile (profile, artis) { this.profile = profile if (artis) { - this.setArtisSet(artis) + this.setArtisData(artis) } } - setArtisSet (ds) { - for (let key in ds) { - this.setArtis(key, ds[key] || {}) - } - } - - setArtis (idx = 1, ds = {}) { - idx = idx.toString().replace('arti', '') - let ret = {} - ret.name = ds.name || ArtifactSet.getArtiNameBySet(ds.set, idx) || '' - ret.set = ds.set || Artifact.getSetNameByArti(ret.name) || '' - ret.level = ds.level || 1 - ret.main = ArtisMark.formatAttr(ds.main || {}) - ret.attrs = [] - for (let attrIdx in ds.attrs || []) { - if (ds.attrs[attrIdx]) { - ret.attrs.push(ArtisMark.formatAttr(ds.attrs[attrIdx])) - } - } - this.artis[idx] = ret - } - - forEach (fn) { - lodash.forEach(this.artis, (ds, idx) => { - if (ds.name) { - fn(ds, idx) - } - }) - } - - _get (key) { - let artis = this.artis - switch (key) { - case 'length': - return lodash.keys(artis).length - } - if (artis[key]) { - return artis[key] - } - } - - toJSON () { - return this.getData('1,2,3,4,5') - } - - get sets () { - return this.getSetData().sets || {} - } - - get names () { - return this.getSetData().names || [] - } - - get hasArtis () { - return !lodash.isEmpty(this.artis) - } - - mainAttr (idx = '') { - if (!idx) { - let ret = {} - for (let i = 1; i <= 5; i++) { - ret[i] = this.mainAttr(i) - } - return ret - } - let main = this.artis[idx]?.main - if (!main) { - return '' - } - return main.key || '' - } - - is (check, pos = '') { - if (pos) { - return this.isAttr(check, pos) - } - let sets = this.getSetData()?.abbrs || [] - let ret = false - Data.eachStr(check, (s) => { - if (sets.includes(s)) { - ret = true - return false - } - }) - return ret - } - - isAttr (attr, pos = '3,4,5') { - let mainAttr = this.mainAttr() - let check = true - Data.eachStr(pos.toString(), (p) => { - let attrs = attr.split(',') - if (!attrs.includes(mainAttr[p]) && (p === '4' && !attrs.includes('dmg') && Format.isElem(mainAttr[p]))) { - check = false - return false - } - }) - return check - } - - // 获取圣遗物数据 - getArtisData () { - let ret = {} - this.forEach((ds, idx) => { - let arti = Artifact.get(ds.name) - ret[idx] = { - ...ds, - name: arti.name, - img: arti.img - } - }) - return ret - } - - /** - * 获取圣遗物套装数据 - * @returns {*|{imgs: *[], names: *[], sets: {}, abbrs: *[], sName: string, name: (string|*)}} - * sets: 套装名:2/4 - * names: [套装名] - * imgs: [img] - * abbrs:[别名] - * name: '组合名字', 若为4件套会使用套装完整名 - * sName: '简写名字',若为4件套也会使用简写 - */ - getSetData () { - if (this._setData) { - return this._setData - } - let setCount = {} - this.forEach((arti, idx) => { - setCount[arti.set] = (setCount[arti.set] || 0) + 1 - }) - let sets = {} - let names = [] - let imgs = [] - let abbrs = [] - let abbrs2 = [] - for (let set in setCount) { - if (setCount[set] >= 2) { - let count = setCount[set] >= 4 ? 4 : 2 - sets[set] = count - let artiSet = ArtifactSet.get(set) - names.push(artiSet.name) - imgs.push(artiSet.img) - abbrs.push(artiSet.abbr + count) - abbrs2.push(artiSet.name + count) - } - } - this._setData = { - sets, - names, - imgs, - abbrs: [...abbrs, ...abbrs2], - name: (abbrs.length > 1 || abbrs2[0]?.length > 7) ? abbrs.join('+') : abbrs2[0], - sName: abbrs.join('+') - } - return this._setData - } - /** * 获取角色配置 * @returns {{classTitle: *, weight: *, posMaxMark: {}, mark: {}, attrs: {}}} @@ -280,24 +119,4 @@ export default class ProfileArtis extends Base { } return ret } - - static _eachArtisSet (sets, fn) { - lodash.forEach(sets || [], (v, k) => { - let artisSet = ArtifactSet.get(k) - if (artisSet) { - if (v >= 4) { - fn(artisSet, 2) - } - fn(artisSet, v) - } - }) - } - - eachArtisSet (fn) { - ProfileArtis._eachArtisSet(this.sets, fn) - } - - static getArtisKeyTitle () { - return ArtisMark.getKeyTitleMap() - } } diff --git a/models/ProfileData.js b/models/ProfileData.js index 1ddb0152..633cba72 100644 --- a/models/ProfileData.js +++ b/models/ProfileData.js @@ -1,27 +1,19 @@ import lodash from 'lodash' -import Base from './Base.js' -import moment from 'moment' +import AvatarData from './AvatarData.js' import { Data } from '../components/index.js' -import { Character, ProfileArtis, ProfileDmg } from './index.js' +import { ProfileArtis, ProfileDmg } from './index.js' import AttrCalc from './profile-lib/AttrCalc.js' -export default class ProfileData extends Base { +export default class ProfileData extends AvatarData { constructor (ds = {}) { - super() - let char = Character.get({ id: ds.id, elem: ds.elem }) - if (!char) { - return false - } - this.id = char.id - this.char = char - this.setBasic(ds) - ds.weapon && this.setWeapon(ds.weapon) - ds.talent && this.setTalent(ds.talent) - this.artis = new ProfileArtis(this.id, this.elem) - ds.artis && this.setArtis(ds.artis) + super(ds) this.calcAttr() } + initArtis () { + this.artis = new ProfileArtis(this.id, this.elem) + } + static create (ds) { let profile = new ProfileData(ds) if (!profile) { @@ -30,71 +22,31 @@ export default class ProfileData extends Base { return profile } + setAttr (ds) { + this.attr = lodash.extend(Data.getData(ds, 'atk,atkBase,def,defBase,hp,hpBase,mastery,recharge'), { + heal: ds.heal || ds.hInc || 0, + cpct: ds.cpct || ds.cRate, + cdmg: ds.cdmg || ds.cDmg, + dmg: ds.dmg || ds.dmgBonus || 0, + phy: ds.phy || ds.phyBonus || 0 + }) + } + calcAttr () { this._attr = AttrCalc.create(this) this.attr = this._attr.calc() } - setBasic (ds = {}) { - this.level = ds.lv || ds.level || 1 - this.cons = ds.cons || 0 - this.fetter = ds.fetter || 0 - this._costume = ds.costume || 0 - this.elem = ds.elem || this.char.elem || '' - this.dataSource = ds.dataSource || 'enka' - this.promote = lodash.isUndefined(ds.promote) ? AttrCalc.calcPromote(this.level) : (ds.promote || 0) - this._time = ds._time || ds.updateTime || new Date() * 1 - } - - setWeapon (ds = {}) { - this.weapon = { - name: ds.name, - star: ds.rank || ds.star || 1, - level: ds.level || ds.lv || 1, - promote: lodash.isUndefined(ds.promote) ? AttrCalc.calcPromote(ds.level || ds.lv || 1) : (ds.promote || 0), - affix: ds.affix - } - let w = this.weapon - if (w.level < 20) { - w.promote = 0 - } - } - setArtis (ds = false) { - this.artis.setProfile(this, ds.artis || ds) - } - - setTalent (ds = {}, mode = 'original') { - this.talent = this.char.getAvatarTalent(ds, this.cons, mode) - } - - get name () { - return this.char?.name || '' + this.artis?.setProfile(this, ds.artis?.artis || ds.artis || ds) } // 判断当前profileData是否具有有效数据 get hasData () { - // 检查数据源 - if (!this.dataSource || !['enka', 'change', 'miao'].includes(this.dataSource)) { - return false - } - // 检查属性 - if (!this.weapon || !this.talent || !this.artis) { - return false - } - // 检查旅行者 - if (['空', '荧'].includes(this.name)) { - return !!this.elem - } - return true + return this.isProfile } - // 判断当前profileData是否具备有效圣遗物信息 - hasArtis () { - return this.hasData && this.artis.length > 0 - } - - get costume () { + get splashCostume () { let costume = this._costume if (lodash.isArray(costume)) { costume = costume[0] @@ -106,46 +58,6 @@ export default class ProfileData extends Base { return [costume, 'normal'] } - get originalTalent () { - return lodash.mapValues(this.talent, (ds) => ds.original) - } - - // toJSON 供保存使用 - toJSON () { - let ret = { - ...this.getData('id,name,elem,level,promote,fetter,costume,cons,talent,attr,weapon,artis,dataSource,_time') - } - ret.talent = lodash.mapValues(this.talent, (ds) => ds.original) - ret.costume = this.costume[0] || 0 - return ret - } - - get updateTime () { - let time = this._time - if (!time) { - return '' - } - if (lodash.isString(time)) { - return moment(time).format('MM-DD HH:mm') - } - if (lodash.isNumber(time)) { - return moment(new Date(time)).format('MM-DD HH:mm') - } - return '' - } - - get dataSourceName () { - return { - enka: 'Enka.Network', - miao: '喵喵Api', - input: 'Input' - }[this.dataSource] || 'Enka.NetWork' - } - - get isProfile () { - return true - } - // 获取当前profileData的圣遗物评分,withDetail=false仅返回简略信息 getArtisMark (withDetail = true) { if (this.hasData) { diff --git a/models/ProfileReq.js b/models/ProfileReq.js index 07f2eb42..004c0646 100644 --- a/models/ProfileReq.js +++ b/models/ProfileReq.js @@ -8,10 +8,17 @@ function sleep (ms) { } export default class ProfileReq extends Base { - constructor ({ e, uid }) { + constructor (e) { super() this.e = e - this.uid = uid + this.uid = e.uid + } + + static create (e) { + if (!e || !e.uid) { + return false + } + return new ProfileReq(e) } async setCd (seconds = 60) { @@ -51,16 +58,14 @@ export default class ProfileReq extends Base { this.e.reply(msg) } - async request (player) { - let Serv = ProfileReq.getServ(this.uid) - let reqParam = await Serv.getReqParam(this.uid) - + async requestProfile (player, serv) { + let reqParam = await serv.getReqParam(this.uid) let cdTime = await this.inCd() if (cdTime) { - // return this.err(`请求过快,请${cdTime}秒后重试..`) + // return this.err(`请求过快,请${cdTime}秒后重试..`) } await this.setCd(20) - // this.msg(`开始获取uid:${this.uid}的数据,可能会需要一定时间~`) + this.msg(`开始获取uid:${this.uid}的数据,可能会需要一定时间~`) await sleep(100) // 发起请求 let data = {} @@ -83,30 +88,20 @@ export default class ProfileReq extends Base { console.log('面板请求错误', e) data = {} } - data = await Serv.response(data, this) + data = await serv.response(data, this) // 设置CD - cdTime = Serv.getCdTime(data) + cdTime = serv.getCdTime(data) if (cdTime) { await this.setCd(cdTime) } if (data === false) { return false } - Serv.updatePlayer(player, data) - cdTime = Serv.getCdTime(data) + serv.updatePlayer(player, data) + cdTime = serv.getCdTime(data) if (cdTime) { await this.setCd(cdTime) } return player } } - -ProfileReq.serv = {} -ProfileReq.regServ = function (serv) { - for (let key in serv) { - ProfileReq.serv[key] = serv[key] - } -} -ProfileReq.getServ = function (uid) { - return ProfileServ.getServ({ uid, serv: ProfileReq.serv }) -} diff --git a/models/ProfileServ.js b/models/ProfileServ.js index 7c3aff2c..98f9bd3e 100644 --- a/models/ProfileServ.js +++ b/models/ProfileServ.js @@ -79,14 +79,3 @@ export default class ProfileServ extends Base { return this.execFn('updatePlayer', [player, data], {}) } } - -ProfileServ.getServ = function ({ uid, serv }) { - let { Miao, Enka } = serv - let token = diyCfg?.miaoApi?.token - let qq = diyCfg?.miaoApi?.qq - - if (qq && token && token.length === 32 && !/^test/.test(token) && Cfg.get('profileServ') === 1) { - return Miao - } - return Enka -} diff --git a/models/index.js b/models/index.js index f76ec989..ee26053e 100644 --- a/models/index.js +++ b/models/index.js @@ -2,10 +2,8 @@ import Base from './Base.js' import Character from './Character.js' import Artifact from './Artifact.js' import ArtifactSet from './ArtifactSet.js' -import Avatar from './Avatar.js' import AvatarData from './AvatarData.js' import AvatarArtis from './AvatarArtis.js' -import AvatarList from './AvatarList.js' import Abyss from './Abyss.js' import Player from './Player.js' import ProfileServ from './ProfileServ.js' @@ -26,9 +24,7 @@ export { Character, Artifact, ArtifactSet, - Avatar, AvatarData, - AvatarList, AvatarArtis, ProfileServ, ProfileReq, diff --git a/models/player-lib/enka.js b/models/player-lib/EnkaApi.js similarity index 76% rename from models/player-lib/enka.js rename to models/player-lib/EnkaApi.js index adda6986..30089001 100644 --- a/models/player-lib/enka.js +++ b/models/player-lib/EnkaApi.js @@ -1,14 +1,13 @@ import lodash from 'lodash' import { Data } from '../../components/index.js' -import { ProfileServ } from '../index.js' -import EnkaData from './enka-data.js' +import EnkaData from './EnkaData.js' +import MiaoData from './MiaoData.js' let HttpsProxyAgent = '' -export default new ProfileServ({ +export default { id: 'enka', cfgKey: 'enkaApi', - // 处理请求参数 async request (api) { let params = { @@ -16,7 +15,6 @@ export default new ProfileServ({ } let proxy = this.getCfg('proxyAgent') if (proxy) { - if (HttpsProxyAgent === '') { HttpsProxyAgent = await import('https-proxy-agent').catch((err) => { logger.error(err) @@ -45,8 +43,14 @@ export default new ProfileServ({ return data }, - userData (data) { - return Data.getData(data, 'name:nickname,avatar:profilePicture.avatarId,level,signature') + updatePlayer (player, data) { + player.setBasicData(Data.getData(data, 'name:nickname,face:profilePicture.avatarID,card:nameCardID,level,word:worldLevel,sign:signature')) + lodash.forEach(data.avatarInfoList, (ds) => { + let ret = EnkaData.setAvatar(player, ds) + if (ret) { + player._update.push(ret.id) + } + }) }, profileData (data) { @@ -64,4 +68,4 @@ export default new ProfileServ({ cdTime (data) { return data.ttl || 60 } -}) +} diff --git a/models/player-lib/EnkaData.js b/models/player-lib/EnkaData.js new file mode 100644 index 00000000..f7cfb023 --- /dev/null +++ b/models/player-lib/EnkaData.js @@ -0,0 +1,105 @@ +import lodash from 'lodash' +import { attrMap, idsMap, artisIdxMap } from './ProfileMeta.js' +import { Character, ArtifactSet } from '../index.js' + +let EnkaData = { + setAvatar (player, data) { + let char = Character.get(data.avatarId) + if (!char) { + return + } + let avatar = player.getAvatar(char.id) + let talentRet = EnkaData.getTalent(char.id, data.skillLevelMap) + avatar.setAvatar({ + level: data.propMap['4001'].val * 1, + promote: data.propMap['1002'].val * 1, + cons: data.talentIdList ? data.talentIdList.length : 0, + fetter: data.fetterInfo.expLevel, + costume: char.checkCostume(data.costumeId) ? data.costumeId : 0, + elem: talentRet.elem, + weapon: EnkaData.getWeapon(data.equipList), + talent: talentRet.talent, + artis: EnkaData.getArtifact(data.equipList) + }, 'enka') + return avatar + }, + + getWeapon (data) { + let ds = {} + lodash.forEach(data, (temp) => { + if (temp.flat && temp.flat.itemType === 'ITEM_WEAPON') { + ds = temp + return false + } + }) + let { weapon, flat } = ds + return { + name: idsMap[flat.nameTextMapHash], + level: weapon.level, + promote: weapon.promoteLevel, + affix: (lodash.values(weapon.affixMap)[0] || 0) + 1 + } + }, + + getTalent (charid, ds = {}) { + let char = Character.get(charid) + let { talentId = {}, talentElem = {}, talentKey = {} } = char.meta + let elem = '' + let idx = 0 + let ret = {} + lodash.forEach(ds, (lv, id) => { + let key + if (talentId[id]) { + let tid = talentId[id] + key = talentKey[tid] + elem = elem || talentElem[tid] + ret[key] = lv + } else { + key = ['a', 'e', 'q'][idx++] + ret[key] = ret[key] || lv + } + }) + return { + elem: elem, + talent: ret + } + }, + + getArtifact (data) { + let ret = {} + let get = function (d) { + if (!d) { + return {} + } + let id = d.appendPropId || d.mainPropId || '' + id = id.replace('FIGHT_PROP_', '') + if (!attrMap[id]) { + return {} + } + return { key: attrMap[id], value: d.statValue } + } + lodash.forEach(data, (ds) => { + let flat = ds.flat || {} + let sub = flat.reliquarySubstats || [] + let idx = artisIdxMap[flat.equipType] + if (!idx) { + return + } + let setName = idsMap[flat.setNameTextMapHash] || '' + ret[idx] = { + name: ArtifactSet.getArtiNameBySet(setName, idx), + level: Math.min(20, ((ds.reliquary && ds.reliquary.level) || 1) - 1), + main: get(flat.reliquaryMainstat), + attrs: [ + get(sub[0]), + get(sub[1]), + get(sub[2]), + get(sub[3]) + ] + } + }) + return ret + } +} + +export default EnkaData diff --git a/models/player-lib/miao.js b/models/player-lib/MiaoApi.js similarity index 89% rename from models/player-lib/miao.js rename to models/player-lib/MiaoApi.js index f60ad8c7..b9812880 100644 --- a/models/player-lib/miao.js +++ b/models/player-lib/MiaoApi.js @@ -1,9 +1,8 @@ import lodash from 'lodash' import { Data } from '../../components/index.js' -import { ProfileServ } from '../index.js' -import MiaoData from './miao-data.js' +import MiaoData from './MiaoData.js' -export default new ProfileServ({ +export default { key: 'miao', name: '喵喵Api', cfgKey: 'miaoApi', @@ -36,4 +35,4 @@ export default new ProfileServ({ } return 60 } -}) +} diff --git a/models/player-lib/miao-data.js b/models/player-lib/MiaoData.js similarity index 65% rename from models/player-lib/miao-data.js rename to models/player-lib/MiaoData.js index 282c49b8..b1cd5e67 100644 --- a/models/player-lib/miao-data.js +++ b/models/player-lib/MiaoData.js @@ -1,54 +1,9 @@ import { Character, Artifact } from '../index.js' import lodash from 'lodash' -const attrMap = { - HP: 'hpPlus', - HP_PERCENT: 'hp', - ATTACK: 'atkPlus', - ATTACK_PERCENT: 'atk', - DEFENSE: 'defPlus', - DEFENSE_PERCENT: 'def', - FIRE_ADD_HURT: '', - ICE_ADD_HURT: 'cryo', - ROCK_ADD_HURT: 'geo', - ELEC_ADD_HURT: 'electro', - WIND_ADD_HURT: 'anemo', - WATER_ADD_HURT: 'hydro', - PHYSICAL_ADD_HURT: 'phy', - GRASS_ADD_HURT: 'dendro', - HEAL_ADD: 'heal', - ELEMENT_MASTERY: 'mastery', - CRITICAL: 'cpct', - CRITICAL_HURT: 'cdmg', - CHARGE_EFFICIENCY: 'recharge' -} - +import { attrMap, artisIdxMap } from './ProfileMeta.js' let MiaoData = { - key: 'miao', - name: '喵喵Api', - - getData (uid, data) { - let ret = { - uid, - chars: {} - } - if (data.cacheExpireAt) { - let exp = Math.max(0, Math.round(data.cacheExpireAt - (new Date() / 1000))) - ret.ttl = Math.max(60, exp) - } - return ret - }, - - getAvatar (ds) { - let char = Character.get(ds.id) - return { - id: ds.id, - name: char ? char.name : '', - dataSource: 'miao', - level: ds.level - } - }, setAvatar (player, ds) { let char = Character.get(ds.id) let avatar = player.getAvatar(ds.id) @@ -65,59 +20,16 @@ let MiaoData = { }, 'miao') return avatar }, + getWeapon (weapon) { return { name: weapon.name, - star: weapon.rank, level: weapon.level, promote: weapon.promoteLevel, affix: (weapon.affixLevel || 0) + 1 } }, - getArtifact (data) { - let ret = {} - let get = function (d) { - if (!d) { - return [] - } - let name = d.name - name = name.replace('FIGHT_PROP_', '') - if (!attrMap[name]) { - return [] - } - let value = d.value - if (value && value < 1) { - value = value * 100 - } - return { key: attrMap[name], value } - } - lodash.forEach(data, (ds) => { - let sub = ds.appendAffix || [] - let idx = { - 生之花: 1, - 死之羽: 2, - 时之沙: 3, - 空之杯: 4, - 理之冠: 5 - }[ds.type] - if (!idx) { - return - } - ret[idx] = { - name: ds.name, - set: Artifact.getSetNameByArti(ds.name) || '', - level: ds.level, - main: get(ds.mainAffix), - attrs: [ - get(sub[0]), - get(sub[1]), - get(sub[2]), - get(sub[3]) - ] - } - }) - return ret - }, + getTalent (charid, data = {}) { let char = Character.get(charid) let { talentId = {}, talentElem = {}, talentKey = {} } = char.meta @@ -144,6 +56,44 @@ let MiaoData = { talent: ret, elem } + }, + + getArtifact (data) { + let ret = {} + let get = function (d) { + if (!d) { + return [] + } + let name = d.name + name = name.replace('FIGHT_PROP_', '') + if (!attrMap[name]) { + return [] + } + let value = d.value + if (value && value < 1) { + value = value * 100 + } + return { key: attrMap[name], value } + } + lodash.forEach(data, (ds) => { + let sub = ds.appendAffix || [] + let idx = artisIdxMap[ds.type] + if (!idx) { + return + } + ret[idx] = { + name: ds.name, + level: ds.level, + main: get(ds.mainAffix), + attrs: [ + get(sub[0]), + get(sub[1]), + get(sub[2]), + get(sub[3]) + ] + } + }) + return ret } } export default MiaoData diff --git a/models/player-lib/Profile.js b/models/player-lib/Profile.js new file mode 100644 index 00000000..f344a41c --- /dev/null +++ b/models/player-lib/Profile.js @@ -0,0 +1,60 @@ +import { ProfileReq, ProfileServ } from '../index.js' +import { Cfg, Data } from '../../components/index.js' + +import enkaCfg from './EnkaApi.js' +import MiaoApi from './MiaoApi.js' + +let { diyCfg } = await Data.importCfg('profile') + +const Profile = { + /** + * 根据UID分配请求服务器 + * @param uid + * @returns {ProfileServ} + */ + getServ (uid) { + let token = diyCfg?.miaoApi?.token + let qq = diyCfg?.miaoApi?.qq + + if (qq && token && token.length === 32 && !/^test/.test(token) && Cfg.get('profileServ') === 1) { + if (!Profile.Miao) { + Profile.Miao = new ProfileServ(MiaoApi) + } + return Profile.Miao + } + if (!Profile.Enka) { + Profile.Enka = new ProfileServ(enkaCfg) + } + return Profile.Enka + }, + + /** + * 更新面板数据 + * @param player + * @param force + * @returns {Promise} + */ + async refreshProfile (player, force = true) { + player._update = [] + let { uid, e } = player + if (uid.toString().length !== 9 || !e) { + return false + } + let req = ProfileReq.create(e) + if (!req) { + return false + } + let serv = Profile.getServ(uid) + try { + await req.requestProfile(player, serv) + player._profile = new Date() * 1 + player.save() + return player._update.length + } catch (err) { + e.reply(`UID:${uid}更新面板失败,更新服务:${serv.name}`) + return false + } + } +} + +export default Profile diff --git a/models/player-lib/enka-meta.js b/models/player-lib/ProfileMeta.js similarity index 95% rename from models/player-lib/enka-meta.js rename to models/player-lib/ProfileMeta.js index a2bab555..930b4f38 100644 --- a/models/player-lib/enka-meta.js +++ b/models/player-lib/ProfileMeta.js @@ -1,4 +1,4 @@ -export default { +export const idsMap = { 20848859: '黑岩斩刀', 33330467: '元素熟练', 37147251: '匣里日月', @@ -473,3 +473,40 @@ export default { FIGHT_PROP_WIND_SUB_HURT: '风元素抗性', level: '等级' } + +// 圣遗物词条映射 +export const attrMap = { + HP: 'hpPlus', + HP_PERCENT: 'hp', + ATTACK: 'atkPlus', + ATTACK_PERCENT: 'atk', + DEFENSE: 'defPlus', + DEFENSE_PERCENT: 'def', + FIRE_ADD_HURT: '', + ICE_ADD_HURT: 'cryo', + ROCK_ADD_HURT: 'geo', + ELEC_ADD_HURT: 'electro', + WIND_ADD_HURT: 'anemo', + WATER_ADD_HURT: 'hydro', + PHYSICAL_ADD_HURT: 'phy', + GRASS_ADD_HURT: 'dendro', + HEAL_ADD: 'heal', + ELEMENT_MASTERY: 'mastery', + CRITICAL: 'cpct', + CRITICAL_HURT: 'cdmg', + CHARGE_EFFICIENCY: 'recharge' +} + +// 圣遗物位置映射 +export const artisIdxMap = { + EQUIP_BRACER: 1, + EQUIP_NECKLACE: 2, + EQUIP_SHOES: 3, + EQUIP_RING: 4, + EQUIP_DRESS: 5, + 生之花: 1, + 死之羽: 2, + 时之沙: 3, + 空之杯: 4, + 理之冠: 5 +} \ No newline at end of file diff --git a/models/player-lib/enka-data.js b/models/player-lib/enka-data.js deleted file mode 100644 index 6944ee75..00000000 --- a/models/player-lib/enka-data.js +++ /dev/null @@ -1,227 +0,0 @@ -import lodash from 'lodash' -import enkaMeta from './enka-meta.js' -import { Character, ArtifactSet, ProfileData } from '../index.js' - -const artiIdx = { - EQUIP_BRACER: 1, - EQUIP_NECKLACE: 2, - EQUIP_SHOES: 3, - EQUIP_RING: 4, - EQUIP_DRESS: 5 -} - -const attrMap = { - HP: '小生命', - HP_PERCENT: '大生命', - ATTACK: '小攻击', - ATTACK_PERCENT: '大攻击', - DEFENSE: '小防御', - DEFENSE_PERCENT: '大防御', - FIRE_ADD_HURT: '火元素伤害加成', - ICE_ADD_HURT: '冰元素伤害加成', - ROCK_ADD_HURT: '岩元素伤害加成', - ELEC_ADD_HURT: '雷元素伤害加成', - WIND_ADD_HURT: '风元素伤害加成', - WATER_ADD_HURT: '水元素伤害加成', - PHYSICAL_ADD_HURT: '物理伤害加成', - GRASS_ADD_HURT: '草元素伤害加成', - HEAL_ADD: '治疗加成', - ELEMENT_MASTERY: '元素精通', - CRITICAL: '暴击率', - CRITICAL_HURT: '暴击伤害', - CHARGE_EFFICIENCY: '充能效率' -} - -let EnkaData = { - getProfile (data) { - let char = Character.get(data.avatarId) - let profile = new ProfileData({ id: char.id }) - profile.setBasic({ - level: data.propMap['4001'].val * 1, - promote: data.propMap['1002'].val * 1, - cons: data.talentIdList ? data.talentIdList.length : 0, - fetter: data.fetterInfo.expLevel, - costume: char.checkCostume(data.costumeId) ? data.costumeId : 0, - dataSource: 'enka' - }) - profile.setAttr(EnkaData.getAttr(data.fightPropMap)) - profile.setWeapon(EnkaData.getWeapon(data.equipList)) - profile.setArtis(EnkaData.getArtifact(data.equipList)) - let talentRet = EnkaData.getTalent(char.id, data.skillLevelMap) - profile.setTalent(talentRet.talent, 'original') - // 为旅行者增加elem - if (talentRet.elem) { - profile.elem = talentRet.elem - } - return EnkaData.dataFix(profile) - }, - getAttr (data) { - let ret = {} - let attrKey = { - // atk: 2001, - atkBase: 4, - def: 2002, - defBase: 7, - hp: 2000, - hpBase: 1, - mastery: 28, - cpct: { - src: 20, - pct: true - }, - cdmg: { - src: 22, - pct: true - }, - heal: { - src: 26, - pct: true - }, - recharge: { - src: 23, - pct: true - } - } - lodash.forEach(attrKey, (cfg, key) => { - if (!lodash.isObject(cfg)) { - cfg = { src: cfg } - } - let val = data[cfg.src] || 0 - if (cfg.pct) { - val = val * 100 - } - ret[key] = val - }) - ret.atk = data['4'] * (1 + (data['6'] || 0)) + (data['5'] || 0) - let maxDmg = 0 - // 火40 水42 风44 岩45 冰46 雷46 - // 41 雷 - lodash.forEach('40,41,42,43,44,45,45,46'.split(','), (key) => { - maxDmg = Math.max(data[key] * 1, maxDmg) - }) - // phy 30 - ret.dmg = maxDmg * 100 - ret.phy = data['30'] * 100 - - return ret - }, - - getArtifact (data) { - let ret = {} - - let get = function (d) { - if (!d) { - return [] - } - let id = d.appendPropId || d.mainPropId || '' - id = id.replace('FIGHT_PROP_', '') - if (!attrMap[id]) { - return [] - } - return [attrMap[id], d.statValue] - } - lodash.forEach(data, (ds) => { - let flat = ds.flat || {} - let sub = flat.reliquarySubstats || [] - let idx = artiIdx[flat.equipType] - if (!idx) { - return - } - let setName = enkaMeta[flat.setNameTextMapHash] || '' - ret[idx] = { - name: ArtifactSet.getArtiNameBySet(setName, idx), - set: setName, - level: Math.min(20, ((ds.reliquary && ds.reliquary.level) || 1) - 1), - main: get(flat.reliquaryMainstat), - attrs: [ - get(sub[0]), - get(sub[1]), - get(sub[2]), - get(sub[3]) - ] - } - }) - return ret - }, - getWeapon (data) { - let ds = {} - lodash.forEach(data, (temp) => { - if (temp.flat && temp.flat.itemType === 'ITEM_WEAPON') { - ds = temp - return false - } - }) - let { weapon, flat } = ds - return { - name: enkaMeta[flat.nameTextMapHash], - star: flat.rankLevel, - level: weapon.level, - promote: weapon.promoteLevel, - affix: (lodash.values(weapon.affixMap)[0] || 0) + 1 - } - }, - getTalent (charid, ds = {}) { - let char = Character.get(charid) - let { talentId = {}, talentElem = {}, talentKey = {} } = char.meta - let elem = '' - let idx = 0 - let ret = {} - lodash.forEach(ds, (lv, id) => { - let key - if (talentId[id]) { - let tid = talentId[id] - key = talentKey[tid] - elem = elem || talentElem[tid] - ret[key] = lv - } else { - key = ['a', 'e', 'q'][idx++] - ret[key] = ret[key] || lv - } - }) - return { - elem: elem, - talent: ret - } - }, - dataFix (ret) { - if (ret._fix) { - return ret - } - let { attr, id, weapon } = ret - let count = 0 - id = id * 1 - switch (id) { - case 10000052: - // 雷神被动加成fix - attr.dmg = Math.max(0, attr.dmg - (attr.recharge - 100) * 0.4) - break - case 10000041: - // 莫娜被动fix - attr.dmg = Math.max(0, attr.dmg - attr.recharge * 0.2) - break - case 10000070: - // 妮露满命效果fix - if (ret.cons === 6) { - count = Math.floor(attr.hp / 1000) - attr.cpct = Math.max(5, attr.cpct - Math.min(30, count * 0.6)) - attr.cdmg = Math.max(50, attr.cdmg - Math.min(60, count * 1.2)) - } - break - } - let wDmg = { - 息灾: 12, - 波乱月白经津: 12, - 雾切之回光: 12, - 猎人之径: 12 - } - let { name, affix } = weapon - // 修正武器的加伤 - if (wDmg[name]) { - attr.dmg = Math.max(0, attr.dmg - wDmg[name] - wDmg[name] * (affix - 1) / 4) - } - ret._fix = true - return ret - } -} - -export default EnkaData diff --git a/models/profile-lib/AttrCalc.js b/models/profile-lib/AttrCalc.js index f831b7a0..5264bfb0 100644 --- a/models/profile-lib/AttrCalc.js +++ b/models/profile-lib/AttrCalc.js @@ -37,9 +37,6 @@ class AttrCalc { this.setCharAttr() this.setWeaponAttr() this.setArtisAttr() - if (process.argv.includes('web-debug')) { - // console.log(this.attr, this.attr.getAttr()) - } return this.attr.getAttr() } diff --git a/resources/character/profile-detail.html b/resources/character/profile-detail.html index 869524bb..b0fd73d2 100644 --- a/resources/character/profile-detail.html +++ b/resources/character/profile-detail.html @@ -56,7 +56,7 @@
{{if data.dataSource}} - 数据源:{{ {miao:"喵喵Api",enka:"Enka.Network",change:"面板变换"}[data.dataSource]||data.dataSource }} + 数据源:{{ {change:"面板变换"}[data.dataSource]||data.dataSource }} {{/if}} {{if data.updateTime}} {{data.updateTime}}