mirror of
https://github.com/yoimiya-kokomi/miao-plugin.git
synced 2024-11-21 22:48:13 +00:00
初步增加角色详情展示
This commit is contained in:
parent
e03dbeb651
commit
705460abe1
1
.gitignore
vendored
1
.gitignore
vendored
@ -2,3 +2,4 @@
|
|||||||
.idea
|
.idea
|
||||||
/components/cfg.json
|
/components/cfg.json
|
||||||
/resources/miao-res-plus/
|
/resources/miao-res-plus/
|
||||||
|
/components/setting.json
|
||||||
|
@ -2,6 +2,8 @@ import { segment } from "oicq";
|
|||||||
import lodash from "lodash";
|
import lodash from "lodash";
|
||||||
import { Character } from "../components/models.js"
|
import { Character } from "../components/models.js"
|
||||||
import { Cfg } from "../components/index.js";
|
import { Cfg } from "../components/index.js";
|
||||||
|
import Profile from "../components/Profile.js";
|
||||||
|
import Format from "../components/Format.js"
|
||||||
import fs from "fs";
|
import fs from "fs";
|
||||||
import sizeOf from "image-size";
|
import sizeOf from "image-size";
|
||||||
|
|
||||||
@ -46,25 +48,39 @@ export async function init(isUpdate = false) {
|
|||||||
let version = isUpdate ? new Date().getTime() : 0;
|
let version = isUpdate ? new Date().getTime() : 0;
|
||||||
genshin = await import(_path + `/config/genshin/roleId.js?version=${version}`);
|
genshin = await import(_path + `/config/genshin/roleId.js?version=${version}`);
|
||||||
nameID = "";
|
nameID = "";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 查看当前角色
|
// 查看当前角色
|
||||||
export async function character(e, { render, User }) {
|
export async function character(e, { render, User }) {
|
||||||
if (!e.msg) {
|
let msg = e.msg;
|
||||||
|
if (!msg) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
console.log(msg);
|
||||||
if (Cfg.isDisable(e, "char.char")) {
|
if (Cfg.isDisable(e, "char.char")) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let name = e.msg.replace(/#|老婆|老公|[1|2|5][0-9]{8}/g, "").trim();
|
let mode = 'card';
|
||||||
|
if (/详情$/.test(msg)) {
|
||||||
|
mode = 'profile';
|
||||||
|
}
|
||||||
|
|
||||||
|
let name = msg.replace(/#|老婆|老公|详情|[1|2|5][0-9]{8}/g, "").trim();
|
||||||
|
console.log(name);
|
||||||
let char = Character.get(name);
|
let char = Character.get(name);
|
||||||
if (!char) {
|
if (!char) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return renderAvatar(e, char.name, render);
|
console.log(char.id, char.name, mode);
|
||||||
|
|
||||||
|
if (mode === "profile") {
|
||||||
|
return renderProfile(e, char, render);
|
||||||
|
} else {
|
||||||
|
return renderAvatar(e, char.name, render);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let _pokeCharacter = false;
|
let _pokeCharacter = false;
|
||||||
@ -387,6 +403,35 @@ async function getTalent(e, avatars) {
|
|||||||
return skill;
|
return skill;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function getProfile(e) {
|
||||||
|
let MysApi = await e.getMysApi({
|
||||||
|
auth: "cookie",
|
||||||
|
targetType: "self",
|
||||||
|
cookieType: "self",
|
||||||
|
actionName: "更新角色信息"
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!MysApi) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
let selfUser = e.selfUser;
|
||||||
|
if (!selfUser.isCookieUser) {
|
||||||
|
e.reply("仅绑定cookie用户可用")
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
e.reply("开始更新用户信息,可能会需要一定时间");
|
||||||
|
//try {
|
||||||
|
let data = await Profile.request(selfUser.uid);
|
||||||
|
//} catch (err) {
|
||||||
|
|
||||||
|
//e.reply("更新错误");
|
||||||
|
//}
|
||||||
|
if (data) {
|
||||||
|
e.reply("更新成功")
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// 获取角色数据
|
// 获取角色数据
|
||||||
function getCharacterData(avatars) {
|
function getCharacterData(avatars) {
|
||||||
let list = [];
|
let list = [];
|
||||||
@ -461,3 +506,52 @@ function getCharacterData(avatars) {
|
|||||||
set: setArr,
|
set: setArr,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function renderProfile(e, char, render) {
|
||||||
|
let MysApi = await e.getMysApi({
|
||||||
|
auth: "cookie",
|
||||||
|
targetType: "self",
|
||||||
|
cookieType: "self",
|
||||||
|
actionName: "查询角色详情"
|
||||||
|
});
|
||||||
|
|
||||||
|
let selfUser = e.selfUser,
|
||||||
|
uid = selfUser.uid;
|
||||||
|
|
||||||
|
let profile = Profile.get(uid, char.id);
|
||||||
|
if (!profile) {
|
||||||
|
return renderAvatar(e, char.name, render)
|
||||||
|
}
|
||||||
|
|
||||||
|
let a = profile.attr;
|
||||||
|
let c = Format.comma,
|
||||||
|
p = Format.pct;
|
||||||
|
let attr = {
|
||||||
|
hp: c(a.hp),
|
||||||
|
hpPlus: c(a.hp - a.hpBase),
|
||||||
|
atk: c(a.atk),
|
||||||
|
atkPlus: c(a.atk - a.atkBase),
|
||||||
|
def: c(a.def),
|
||||||
|
defPlus: c(a.def - a.defBase),
|
||||||
|
cRate: p(a.cRate),
|
||||||
|
cDmg: p(a.cDmg),
|
||||||
|
mastery: c(a.mastery),
|
||||||
|
recharge: p(a.recharge),
|
||||||
|
dmgBonus: p(a.dmgBonus)
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
let base64 = await render("character", "detail", {
|
||||||
|
save_id: uid,
|
||||||
|
uid: uid,
|
||||||
|
data: profile,
|
||||||
|
meta: char,
|
||||||
|
attr,
|
||||||
|
talentMap: { a: "普攻", e: "战技", q: "爆发" },
|
||||||
|
cfgScale: Cfg.scale(1.25)
|
||||||
|
}, "png");
|
||||||
|
if (base64) {
|
||||||
|
e.reply(segment.image(`base64://${base64}`));
|
||||||
|
}
|
||||||
|
}
|
19
components/Format.js
Normal file
19
components/Format.js
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
let Format = {
|
||||||
|
int: function (d) {
|
||||||
|
return parseInt(d);
|
||||||
|
},
|
||||||
|
comma: function (num, fix = 0) {
|
||||||
|
num = parseFloat((num * 1).toFixed(fix));
|
||||||
|
let [integer, decimal] = String.prototype.split.call(num, '.');
|
||||||
|
integer = integer.replace(/\d(?=(\d{3})+$)/g, '$&,'); // 正则先行断言
|
||||||
|
return `${integer}${decimal ? '.' + decimal : ''}`;
|
||||||
|
},
|
||||||
|
pct: function (num, fix = 1) {
|
||||||
|
return (num * 1).toFixed(fix) + "%";
|
||||||
|
},
|
||||||
|
percent: function (num, fix = 1) {
|
||||||
|
return Format.pct(num * 100, fix);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Format;
|
258
components/Profile.js
Normal file
258
components/Profile.js
Normal file
@ -0,0 +1,258 @@
|
|||||||
|
import fs from "fs";
|
||||||
|
import fetch from "node-fetch";
|
||||||
|
import lodash from "lodash";
|
||||||
|
|
||||||
|
const _path = process.cwd();
|
||||||
|
const cfgPath = `${_path}/plugins/miao-plugin/components/setting.json`;
|
||||||
|
let cfg = {};
|
||||||
|
try {
|
||||||
|
if (fs.existsSync(cfgPath)) {
|
||||||
|
cfg = JSON.parse(fs.readFileSync(cfgPath, "utf8")) || {};
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
// do nth
|
||||||
|
}
|
||||||
|
|
||||||
|
const userPath = `${_path}/data/UserData/`;
|
||||||
|
|
||||||
|
if (!fs.existsSync(userPath)) {
|
||||||
|
fs.mkdirSync(userPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
const artifactMap = {
|
||||||
|
'生命值': {
|
||||||
|
title: "小生命"
|
||||||
|
},
|
||||||
|
'生命值_百分比': {
|
||||||
|
title: "大生命",
|
||||||
|
pct: true
|
||||||
|
},
|
||||||
|
'暴击率': {
|
||||||
|
title: "暴击率",
|
||||||
|
pct: true
|
||||||
|
},
|
||||||
|
'暴击伤害': {
|
||||||
|
title: "爆伤",
|
||||||
|
pct: true
|
||||||
|
},
|
||||||
|
'防御力': {
|
||||||
|
title: "小防御"
|
||||||
|
},
|
||||||
|
'防御力_百分比': {
|
||||||
|
title: "大防御",
|
||||||
|
pct: true
|
||||||
|
},
|
||||||
|
'攻击力': {
|
||||||
|
title: "小攻击"
|
||||||
|
},
|
||||||
|
'攻击力_百分比': {
|
||||||
|
title: "大攻击",
|
||||||
|
pct: true
|
||||||
|
},
|
||||||
|
'元素精通': {
|
||||||
|
title: "精通"
|
||||||
|
},
|
||||||
|
'元素充能效率': {
|
||||||
|
title: "充能",
|
||||||
|
pct: true
|
||||||
|
},
|
||||||
|
'治疗加成': {
|
||||||
|
title: "治疗",
|
||||||
|
pct: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let Data = {
|
||||||
|
getData(uid, data) {
|
||||||
|
let ret = {
|
||||||
|
uid,
|
||||||
|
chars: {}
|
||||||
|
};
|
||||||
|
|
||||||
|
lodash.forEach({
|
||||||
|
name: "角色名称",
|
||||||
|
avatar: "头像ID",
|
||||||
|
lv: "冒险等阶"
|
||||||
|
}, (title, key) => {
|
||||||
|
ret[key] = data[title] || "";
|
||||||
|
})
|
||||||
|
|
||||||
|
console.log(data.items.length)
|
||||||
|
|
||||||
|
lodash.forEach(data.items, (ds) => {
|
||||||
|
let char = Data.getAvatar(ds);
|
||||||
|
console.log(char)
|
||||||
|
ret.chars[char.id] = char;
|
||||||
|
});
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
},
|
||||||
|
getAvatar(data) {
|
||||||
|
return {
|
||||||
|
id: data["英雄Id"],
|
||||||
|
lv: data['等级'],
|
||||||
|
attr: Data.getAttr(data),
|
||||||
|
weapon: Data.getWeapon(data),
|
||||||
|
artis: Data.getArtifact(data),
|
||||||
|
cons: data["命之座数量"] * 1 || 0,
|
||||||
|
talent: Data.getTalent(data)
|
||||||
|
};
|
||||||
|
},
|
||||||
|
getAttr(data) {
|
||||||
|
let ret = {};
|
||||||
|
let attrKey = {
|
||||||
|
atk: "攻击力_总",
|
||||||
|
atkBase: "属性攻击力",
|
||||||
|
def: "防御力_总",
|
||||||
|
defBase: "属性防御力",
|
||||||
|
hp: "生命值上限_总",
|
||||||
|
hpBase: "属性生命值上限",
|
||||||
|
mastery: "属性元素精通",
|
||||||
|
cRate: {
|
||||||
|
title: "属性暴击率",
|
||||||
|
pct: true
|
||||||
|
},
|
||||||
|
cDmg: {
|
||||||
|
title: "属性暴击伤害",
|
||||||
|
pct: true
|
||||||
|
},
|
||||||
|
hInc: {
|
||||||
|
title: "属性治疗加成",
|
||||||
|
pct: true
|
||||||
|
},
|
||||||
|
recharge: {
|
||||||
|
title: "属性元素充能效率",
|
||||||
|
pct: true
|
||||||
|
}
|
||||||
|
};
|
||||||
|
lodash.forEach(attrKey, (cfg, key) => {
|
||||||
|
if (typeof (cfg) === "string") {
|
||||||
|
cfg = { title: cfg };
|
||||||
|
}
|
||||||
|
let val = data[cfg.title] || "";
|
||||||
|
if (cfg.pct) {
|
||||||
|
val = (val * 100).toFixed(2)
|
||||||
|
}
|
||||||
|
ret[key] = val;
|
||||||
|
});
|
||||||
|
let maxDmg = 0;
|
||||||
|
lodash.forEach("火水草雷风冰岩".split(""), (key) => {
|
||||||
|
maxDmg = Math.max(data[`属性${key}元素伤害加成`] * 1, maxDmg);
|
||||||
|
});
|
||||||
|
ret.dmgBonus = (maxDmg * 100).toFixed(2);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
},
|
||||||
|
getWeapon(data) {
|
||||||
|
return {
|
||||||
|
name: data['武器名称'],
|
||||||
|
lv: data['武器等级'],
|
||||||
|
refine: data["武器精炼"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
getArtifact(data) {
|
||||||
|
let ret = {};
|
||||||
|
let get = function (idx, key) {
|
||||||
|
let v = data[`圣遗物${idx}${key}`];
|
||||||
|
let ret = /^([^\d]*)([\d\.\-]*)$/.exec(v);
|
||||||
|
if (ret && ret[1]) {
|
||||||
|
let title = ret[1], val = ret[2];
|
||||||
|
if (artifactMap[title]) {
|
||||||
|
if (artifactMap[title].pct) {
|
||||||
|
val = (val * 100).toFixed(2);
|
||||||
|
}
|
||||||
|
title = artifactMap[title].title;
|
||||||
|
}
|
||||||
|
return [title, val];
|
||||||
|
}
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let idx = 1; idx <= 5; idx++) {
|
||||||
|
ret[`arti${idx}`] = {
|
||||||
|
name: data[`圣遗物${idx}名称`],
|
||||||
|
type: data[`圣遗物${idx}类型`],
|
||||||
|
main: get(idx, "主词条"),
|
||||||
|
attrs: [
|
||||||
|
get(idx, "副词条1"),
|
||||||
|
get(idx, "副词条2"),
|
||||||
|
get(idx, "副词条3"),
|
||||||
|
get(idx, "副词条4"),
|
||||||
|
]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
},
|
||||||
|
getTalent(data) {
|
||||||
|
let ret = {};
|
||||||
|
lodash.forEach({
|
||||||
|
a: 1,
|
||||||
|
e: 2,
|
||||||
|
q: 3
|
||||||
|
}, (idx, key) => {
|
||||||
|
let val = data[`天赋主动名称${idx}`]
|
||||||
|
let regRet = /等级(\d*)$/.exec(val);
|
||||||
|
if (regRet && regRet[1]) {
|
||||||
|
ret[key] = regRet[1] * 1 || 1
|
||||||
|
} else {
|
||||||
|
ret[key] = 1;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let Profile = {
|
||||||
|
async request(uid) {
|
||||||
|
if (!cfg.api) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
const api = cfg.api + uid;
|
||||||
|
let req = await fetch(api);
|
||||||
|
let data = await req.text();
|
||||||
|
data = data.replace(/\x00/g, '');
|
||||||
|
console.log(data);
|
||||||
|
fs.writeFileSync(userPath + "/test.json", data);
|
||||||
|
data = JSON.parse(data);
|
||||||
|
console.log(data);
|
||||||
|
let userData = {};
|
||||||
|
if (data && data["角色名称"]) {
|
||||||
|
userData = Profile.save(uid, data)
|
||||||
|
}
|
||||||
|
return userData;
|
||||||
|
},
|
||||||
|
|
||||||
|
save(uid, ds) {
|
||||||
|
let userData = {};
|
||||||
|
const userFile = `${userPath}/${uid}.json`;
|
||||||
|
if (fs.existsSync(userFile)) {
|
||||||
|
userData = JSON.parse(fs.readFileSync(userFile, "utf8")) || {};
|
||||||
|
}
|
||||||
|
|
||||||
|
let data = Data.getData(uid, ds);
|
||||||
|
|
||||||
|
lodash.assignIn(userData, lodash.pick(data, "uid,name,lv,avatar".split(",")));
|
||||||
|
|
||||||
|
userData.chars = userData.chars || {};
|
||||||
|
lodash.forEach(data.chars, (char, charId) => {
|
||||||
|
userData.chars[charId] = char;
|
||||||
|
});
|
||||||
|
|
||||||
|
fs.writeFileSync(userFile, JSON.stringify(userData), "", " ");
|
||||||
|
return userData;
|
||||||
|
},
|
||||||
|
get(uid, charId) {
|
||||||
|
const userFile = `${userPath}/${uid}.json`;
|
||||||
|
let userData = {};
|
||||||
|
if (fs.existsSync(userFile)) {
|
||||||
|
userData = JSON.parse(fs.readFileSync(userFile, "utf8")) || {};
|
||||||
|
}
|
||||||
|
console.log(charId, lodash.keys(userData.chars));
|
||||||
|
if (userData && userData.chars && userData.chars[charId]) {
|
||||||
|
return userData.chars[charId];
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
export default Profile;
|
20
index.js
20
index.js
@ -1,4 +1,4 @@
|
|||||||
import { character, wife, wifeReg } from "./apps/character.js";
|
import { character, getProfile, wife, wifeReg } from "./apps/character.js";
|
||||||
import { consStat, abyssPct } from "./apps/stat.js";
|
import { consStat, abyssPct } from "./apps/stat.js";
|
||||||
import { wiki } from "./apps/wiki.js";
|
import { wiki } from "./apps/wiki.js";
|
||||||
import { help } from "./apps/help.js";
|
import { help } from "./apps/help.js";
|
||||||
@ -6,29 +6,37 @@ import lodash from "lodash";
|
|||||||
|
|
||||||
import { rule as adminRule, updateRes, sysCfg } from "./apps/admin.js";
|
import { rule as adminRule, updateRes, sysCfg } from "./apps/admin.js";
|
||||||
|
|
||||||
export { character, wife, consStat, abyssPct, wiki, updateRes, sysCfg, help };
|
export { character, wife, consStat, abyssPct, wiki, updateRes, sysCfg, help, getProfile };
|
||||||
|
|
||||||
|
|
||||||
let rule = {
|
let rule = {
|
||||||
character: {
|
character: {
|
||||||
reg: "^#(喵喵)?(.*)?$",
|
reg: "^#(喵喵)?(.*)(详情)?$",
|
||||||
describe: "【#刻晴】角色详情",
|
describe: "【#角色】角色详情",
|
||||||
},
|
},
|
||||||
wife: {
|
wife: {
|
||||||
reg: wifeReg,
|
reg: wifeReg,
|
||||||
describe: "【#老婆,#老公,#女儿】角色详情",
|
describe: "【#角色】#老公 #老婆 查询",
|
||||||
},
|
},
|
||||||
consStat: {
|
consStat: {
|
||||||
reg: "^#(喵喵)?角色(持有|持有率|命座|命之座|.命)(分布|统计)?$",
|
reg: "^#(喵喵)?角色(持有|持有率|命座|命之座|.命)(分布|统计)?$",
|
||||||
|
describe: "【#统计】 #角色持有率 #角色5命统计",
|
||||||
},
|
},
|
||||||
abyssPct: {
|
abyssPct: {
|
||||||
reg: "^#(喵喵)?深渊(第?.{1,2}层)?(角色)?出场(率|统计)*$",
|
reg: "^#(喵喵)?深渊(第?.{1,2}层)?(角色)?出场(率|统计)*$",
|
||||||
|
describe: "【#统计】 #深渊出场率 #深渊12层出场率",
|
||||||
},
|
},
|
||||||
wiki: {
|
wiki: {
|
||||||
reg: "^#(喵喵)?.*(天赋|技能|命座|命之座|资料|照片|写真|图片|插画)$",
|
reg: "^#(喵喵)?.*(天赋|技能|命座|命之座|资料|照片|写真|图片|插画)$",
|
||||||
|
describe: "【#资料】 #神里天赋 #夜兰命座",
|
||||||
},
|
},
|
||||||
help: {
|
help: {
|
||||||
reg: "^#?(喵喵)?(命令|帮助|菜单|help|说明|功能|指令|使用说明)$"
|
reg: "^#?(喵喵)?(命令|帮助|菜单|help|说明|功能|指令|使用说明)$",
|
||||||
|
describe: "【#帮助】 #喵喵帮助",
|
||||||
|
},
|
||||||
|
getProfile: {
|
||||||
|
reg: "^#获取游戏角色详情$",
|
||||||
|
describe: "【#角色】 获取游戏橱窗详情数据",
|
||||||
},
|
},
|
||||||
...adminRule
|
...adminRule
|
||||||
};
|
};
|
||||||
|
@ -18,6 +18,12 @@
|
|||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
}
|
}
|
||||||
|
@font-face {
|
||||||
|
font-family: "YS";
|
||||||
|
src: url("../common/font/HYWenHei-55W.ttf");
|
||||||
|
font-weight: normal;
|
||||||
|
font-style: normal;
|
||||||
|
}
|
||||||
|
|
||||||
* {
|
* {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
Loading…
Reference in New Issue
Block a user