miao-plugin/components/Profile.js
yoimiya-kokomi b9eb8695ed * #刻晴 角色卡片功能升级
* `#老婆设置刻晴,心海`不再检查是否具有角色或展示在米游社展柜
    * `#刻晴` 角色卡片优先使用面板数据进行展示,无面板数据时使用米游社数据
    * 在未能获取到角色数据时也会展示角色卡片
    * 角色卡片后续会进行样式升级,按需展示更多内容
* `#深渊出场率`增加楼层排序,以防止服务侧数据乱序导致顺序错乱
* B服面板的天赋与皇冠信息现在可以正确的展示了
2022-06-30 04:40:06 +08:00

293 lines
8.2 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import fs from "fs";
import lodash from "lodash";
import Format from "./Format.js";
import Character from "./models/Character.js";
import Reliquaries from "./models/Reliquaries.js";
import Miao from "./profile-data/miao.js";
import Enka from "./profile-data/enka.js";
const _path = process.cwd();
const cfgPath = `${_path}/plugins/miao-plugin/config.js`;
let config = {};
if (fs.existsSync(cfgPath)) {
let fileData = await import (`file://${cfgPath}`);
if (fileData && fileData.config) {
config = fileData.config;
}
}
const userPath = `${_path}/data/UserData/`;
if (!fs.existsSync(userPath)) {
fs.mkdirSync(userPath);
}
function sleep(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
function getServ(uid) {
if (config.profileApi) {
return config.profileApi({ Enka, Miao })
}
if ((uid + '')[0] === '5') {
return Miao;
}
return Enka;
}
let Profile = {
async request(uid, e) {
if (uid.toString().length !== 9) {
return false;
}
let Serv = getServ(uid);
let inCd = await redis.get(`miao:role-all:${uid}`);
if (inCd === 'loading') {
e.reply("请求过快,请稍后重试..");
return false;
} else if (inCd === 'pending' && false) {
e.reply(`距上次请求刷新成功间隔小于${Serv.cd}分钟,请稍后重试..`);
return false;
}
await redis.set(`miao:role-all:${uid}`, 'loading', { EX: 20 });
e.reply("开始获取数据,可能会需要一定时间~");
await sleep(1000);
let data;
try {
data = await Serv.request({ uid, e, config });
// enka服务测冷却时间5分钟
await redis.set(`miao:role-all:${uid}`, 'pending', { EX: Serv.cd * 60 });
return Profile.save(uid, data, Serv.key);
} catch (err) {
console.log(err);
e.reply(`请求失败`);
return false;
}
},
save(uid, data, dataSource = 'enka') {
let userData = {};
const userFile = `${userPath}/${uid}.json`;
if (fs.existsSync(userFile)) {
userData = JSON.parse(fs.readFileSync(userFile, "utf8")) || {};
}
lodash.assignIn(userData, lodash.pick(data, "uid,name,lv,avatar".split(",")));
userData.chars = userData.chars || {};
lodash.forEach(data.chars, (char, charId) => {
let original = userData.chars[charId] || {};
if (char.dataSource === "miao-pre" && original && original.dataSource) {
original.dataSource = char.dataSource;
} else {
userData.chars[charId] = char;
}
});
fs.writeFileSync(userFile, JSON.stringify(userData), "", " ");
return data;
},
saveCharData(uid, ds) {
if (!uid || !ds.id) {
return;
}
let userData = {};
const userFile = `${userPath}/${uid}.json`;
if (fs.existsSync(userFile)) {
userData = JSON.parse(fs.readFileSync(userFile, "utf8")) || {};
}
userData.chars = userData.chars || {};
userData.chars[ds.id] = ds;
fs.writeFileSync(userFile, JSON.stringify(userData), "", " ");
return ds;
},
_get(uid, charId) {
const userFile = `${userPath}/${uid}.json`;
let userData = {};
if (fs.existsSync(userFile)) {
userData = JSON.parse(fs.readFileSync(userFile, "utf8")) || {};
}
if (userData && userData.chars && userData.chars[charId]) {
return userData.chars[charId];
}
return false;
},
async get(uid, charId, onlyAvailable = false) {
if (onlyAvailable) {
let data = await Profile.get(uid, charId);
if (data && data.dataSource && data.dataSource !== "input") {
return data;
}
return false;
}
let data = Profile._get(uid, charId);
let Serv = getServ(uid);
if (Serv.getCharData && data && data.id) {
return await Serv.getCharData(uid, data, Profile.saveCharData);
}
return data;
},
getAll(uid) {
const userFile = `${userPath}/${uid}.json`;
let userData = {};
if (fs.existsSync(userFile)) {
userData = JSON.parse(fs.readFileSync(userFile, "utf8")) || {};
}
if (userData && userData.chars) {
return userData.chars;
}
return false;
},
formatArti(ds, markCfg = false, isMain = false) {
if (lodash.isArray(ds[0])) {
let ret = [];
lodash.forEach(ds, (d) => {
ret.push(Profile.formatArti(d, markCfg, isMain));
})
return ret;
}
let title = ds[0], key = "", val = ds[1], num = ds[1];
if (!title || title === "undefined") {
return [];
}
if (/伤害加成/.test(title) && val < 1) {
val = Format.pct(val * 100);
num = num * 100;
} else if (/伤害加成|大|暴|充能|治疗/.test(title)) {
val = Format.pct(val);
} else {
val = Format.comma(val, 1);
}
if (/元素伤害加成/.test(title)) {
title = title.replace("元素伤害", "伤");
key = "dmg";
} else if (title === "物理伤害加成") {
title = "物伤加成";
key = "phy";
}
key = key || keyMap[title];
let mark = 0;
if (markCfg) {
mark = Format.comma(markCfg[title] * num || 0);
if (isMain) {
mark = mark / 4;
}
}
return { title, val, mark };
},
getArtiMark(data, ds) {
Reliquaries.getMark(data)
let total = 0;
lodash.forEach(data, (ret) => {
if (ret[0] && ret[1]) {
total += mark[ret[0]] * ret[1];
}
})
if (ds && /暴/.test(ds[0])) {
total += 20;
}
return total;
},
inputProfile(uid, e) {
let { avatar, inputData } = e;
let char = Character.get(avatar);
let originalData = Profile._get(uid, char.id);
if (!originalData || !['enka', 'input2'].includes(originalData.dataSource)) {
return `请先获取${char.name}的面板数据后,再进行面板数据更新`;
}
inputData = inputData.replace("#", "");
inputData = inputData.replace(/||、|\n|\t/g, ",");
let attr = originalData.attr || {};
let attrMap = {
hp: /生命/,
def: /防御/,
atk: /攻击/,
mastery: /精通/,
cRate: /(暴击率|暴率|暴击$)/,
cDmg: /(暴伤|暴击伤害)/,
hInc: /治疗/,
recharge: /充能/,
dmgBonus: /[火|水|雷|草|风|岩|冰|素|^]伤/,
phyBonus: /(物理|物伤)/
}
lodash.forEach(inputData.split(","), (ds, idx) => {
ds = ds.trim();
if (!ds) {
return;
}
let dRet = /(.*?)([0-9\.\+\s]+)/.exec(ds);
if (!dRet || !dRet[1] || !dRet[2]) {
return;
}
let name = dRet[1].trim(),
data = dRet[2].trim();
name = name.replace("爆", "暴");
let range = (src, min = 0, max = 1200) => Math.max(min, Math.min(max, src * 1 || 0));
lodash.forEach(attrMap, (reg, key) => {
if (reg.test(name)) {
let tmp = data.split("+");
switch (key) {
case "hp":
attr[key + "Base"] = range(tmp[0].trim(), 0, 16000);
attr[key] = range(tmp[0].trim() * 1 + tmp[1].trim() * 1, attr[key + "Base"], 50000);
break;
case "def":
case "atk":
attr[key + "Base"] = range(tmp[0].trim(), 0, 1100);
attr[key] = range(tmp[0].trim() * 1 + tmp[1].trim() * 1, attr[key + "Base"], 4500);
break;
case "mastery":
attr[key] = range(data, 0, 1200);
break;
case "cRate":
attr[key] = range(data, -95, 120);
break;
case "cDmg":
attr[key] = range(data, 0, 320);
break;
case "recharge":
case "hInc":
attr[key] = range(data, 0, 400);
break;
case "dmgBonus":
case "phyBonus":
attr[key] = range(data, 0, 200);
break;
}
}
})
})
if (lodash.keys(attr) < 3) {
return false;
}
originalData.dataSource = "input2";
originalData.attr = attr;
let userData = {};
const userFile = `${userPath}/${uid}.json`;
if (fs.existsSync(userFile)) {
userData = JSON.parse(fs.readFileSync(userFile, "utf8")) || {};
}
userData.chars = userData.chars || {};
userData.chars[avatar] = originalData;
fs.writeFileSync(userFile, JSON.stringify(userData), "", " ");
return true;
}
};
export default Profile;