miao-plugin/tools/char-data-sprider.js

255 lines
8.0 KiB
JavaScript

import fs from 'fs'
import cheerio from 'cheerio'
import lodash from 'lodash'
import fetch from 'node-fetch'
import ImgDownloader from './sprider/ImgDown.js'
import CharData from './sprider/CharData.js'
import { Data } from '../components/index.js'
import tId from './sprider/TalentId.js'
const _path = process.cwd()
const _root = _path + '/plugins/miao-plugin/'
const _mRoot = _root + 'resources/meta/material/'
let mData = {}
if (fs.existsSync(_mRoot + 'data.json')) {
mData = JSON.parse(fs.readFileSync(_mRoot + 'data.json', 'utf8'))
}
const tElems = ['anemo', 'geo', 'electro', 'dendro']
let getCharData = async function (id, key, name = '', _id = id) {
let idNum = (id < 10 ? '0' : '') + (id < 100 ? '0' : '') + id
let url = `https://genshin.honeyhunterworld.com/${key}_${idNum}/?lang=CHS`
console.log('req: ' + url)
let req = await fetch(url, {
method: 'GET',
headers: {
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36 Edg/105.0.1343.20',
referer: 'https://genshin.honeyhunterworld.com/fam_chars/?lang=CHS',
'sec-ch-ua': '"Microsoft Edge";v = "105", " Not;A Brand";v = "99", "Chromium";v = "105"',
'sec-ch-ua-mobile': '?0',
'sec-ch-ua-platform': 'Windows',
'sec-fetch-dest': 'document',
'sec-fetch-mode': 'navigate',
'sec-fetch-site': 'none',
'sec-fetch-user': '?1',
'upgrade-insecure-requests': 1
}
})
let txt = await req.text()
const $ = cheerio.load(txt)
let sTxt = /sortable_data.push\((.*)\)/.exec(txt)
if (sTxt && sTxt[1]) {
// eslint-disable-next-line no-eval
let tmp = eval(sTxt[1])
for (let idx in tmp) {
let t = tmp[idx].join('')
if (/Namecard/.test(t)) {
let r = /\/i_([n\d]+)\/\?/.exec(t)
if (r && r[1]) {
$._nid = r[1]
}
}
}
}
let data = CharData.getBasic($, id, name, _id)
name = name || data.name
let imgs = new ImgDownloader(name)
$.imgs = imgs
let attr = CharData.getDetailAttr($)
let ld = attr.details['90']
data.baseAttr = {
hp: ld[0] * 1,
atk: ld[1] * 1,
def: ld[2] * 1
}
data.growAttr = {
key: attr.keys[3],
value: ld[3]
}
let details = []
let talentElem = {}
let talentId
let talentKey
if (data.elem === 'multi') {
talentKey = {}
talentId = {}
for (let idx in tElems) {
let detail = CharData.getDetail($, id, name, idx * 1 + 1, tElems[idx])
detail.attr = attr
detail.elem = tElems[idx]
details.push(detail)
lodash.forEach(detail.talent, (ds, k) => {
talentKey[ds.id] = k
if (k === 'e' || k === 'q') {
talentElem[ds.id] = tElems[idx]
}
})
const te = {
anemo: 4,
geo: 6,
electro: 7,
dendro: 8
}
let cid = `1000000${id}-${id}0${te[tElems[idx]]}`
lodash.forEach(tId[cid].ProudMap || {}, (v, k) => {
talentId[k] = v
})
}
} else {
details.push(CharData.getDetail($, id, name))
talentId = tId[(10000000 + id * 1)]?.ProudMap || {}
}
let detail = details[0]
let { talent, cons } = detail
// data.talent = lodash.mapValues(talent, (t) => t.name)
data.talentKey = talentKey || lodash.invert(lodash.mapValues(talent, (t) => t.id))
data.talentId = talentId
if (data.elem === 'multi') {
data.talentElem = talentElem
}
data.talentCons = CharData.getConsTalent(talent, cons)
/*
data.passive = lodash.map(passive, (t) => t.name)
data.cons = lodash.map(cons, (t) => t.name)
*/
data.materials = CharData.getMaterials($, mData)
CharData.getImgs($)
return {
data,
details,
imgs
}
}
function checkName (name) {
let charPath = `resources/meta/character/${name}/`
Data.createDir(charPath)
if (name === '旅行者') {
for (let idx in tElems) {
Data.createDir(`${charPath}${tElems[idx]}/icons`)
}
} else {
Data.createDir(`${charPath}/icons`)
}
Data.createDir(`${charPath}/imgs`)
let data = Data.readJSON(`${charPath}/data.json`)
return data.ver * 1 > 1
}
async function saveCharData (id, key, name = '', force = false, _id = id) {
if (!id || !key) {
return
}
if (name && checkName(name) && !force) {
return
}
let { data, details, imgs } = await getCharData(id, key, name, _id)
name = name || data.name
if (!name) {
console.log(`角色名不存在${id}:${key}`)
return
}
if (checkName(name) && !force) {
return
}
let charPath = `${_path}/plugins/miao-plugin/resources/meta/character/${name}/`
fs.writeFileSync(`${charPath}data.json`, JSON.stringify(data, '', 2))
if (details.length === 1) {
fs.writeFileSync(`${charPath}detail.json`, JSON.stringify(details[0], '', 2))
} else if (data.id === 20000000) {
for (let idx in details) {
let detail = details[idx]
fs.writeFileSync(`${charPath}/${detail.elem}/detail.json`, JSON.stringify(detail, '', 2))
}
}
console.log(data.name + '数据下载完成')
if (![10000005, 10000007].includes(data.id)) {
await imgs.download()
console.log(data.name + '图像全部下载完成')
}
}
async function down (name = '', force = false) {
if (name === '') {
name = lodash.keys(charData).join(',')
}
let names = name.split(',')
for (let id in charData) {
let ds = charData[id]
if (!names.includes(id) && !names.includes(ds.key) && !names.includes(ds.name)) {
continue
}
await saveCharData(ds.id || id, ds.key, ds.name, force, id)
}
fs.writeFileSync(`${_mRoot}data.json`, JSON.stringify(mData, '', 2))
}
const charData = {
2: { key: 'ayaka', name: '神里绫华' },
3: { key: 'qin', name: '琴' },
4: { key: 'playergirl', name: '旅行者', id: 7 },
5: { key: 'playerboy', name: '空' },
6: { key: 'lisa', name: '丽莎' },
7: { key: 'playergirl', name: '荧' },
14: { key: 'barbara', name: '芭芭拉' },
15: { key: 'kaeya', name: '凯亚' },
16: { key: 'diluc', name: '迪卢克' },
20: { key: 'razor', name: '雷泽' },
21: { key: 'ambor', name: '安柏' },
22: { key: 'venti', name: '温迪' },
23: { key: 'xiangling', name: '香菱' },
24: { key: 'beidou', name: '北斗' },
25: { key: 'xingqiu', name: '行秋' },
26: { key: 'xiao', name: '魈' },
27: { key: 'ningguang', name: '凝光' },
29: { key: 'klee', name: '可莉' },
30: { key: 'zhongli', name: '钟离' },
31: { key: 'fischl', name: '菲谢尔' },
32: { key: 'bennett', name: '班尼特' },
33: { key: 'tartaglia', name: '达达利亚' },
34: { key: 'noel', name: '诺艾尔' },
35: { key: 'qiqi', name: '七七' },
36: { key: 'chongyun', name: '重云' },
37: { key: 'ganyu', name: '甘雨' },
38: { key: 'albedo', name: '阿贝多' },
39: { key: 'diona', name: '迪奥娜' },
41: { key: 'mona', name: '莫娜' },
42: { key: 'keqing', name: '刻晴' },
43: { key: 'sucrose', name: '砂糖' },
44: { key: 'xinyan', name: '辛焱' },
45: { key: 'rosaria', name: '罗莎莉亚' },
46: { key: 'hutao', name: '胡桃' },
47: { key: 'kazuha', name: '枫原万叶' },
48: { key: 'feiyan', name: '烟绯' },
49: { key: 'yoimiya', name: '宵宫' },
50: { key: 'tohma', name: '托马' },
51: { key: 'eula', name: '优菈' },
52: { key: 'shougun', name: '雷电将军' },
53: { key: 'sayu', name: '早柚' },
54: { key: 'kokomi', name: '珊瑚宫心海' },
55: { key: 'gorou', name: '五郎' },
56: { key: 'sara', name: '九条裟罗' },
57: { key: 'itto', name: '荒泷一斗' },
58: { key: 'yae', name: '八重神子' },
59: { key: 'heizo', name: '鹿野院平藏' },
60: { key: 'yelan', name: '夜兰' },
62: { key: 'aloy', name: '埃洛伊' },
63: { key: 'shenhe', name: '申鹤' },
64: { key: 'yunjin', name: '云堇' },
65: { key: 'shinobu', name: '久岐忍' },
66: { key: 'ayato', name: '神里绫人' },
67: { key: 'collei', name: '柯莱' },
68: { key: 'dori', name: '多莉' },
69: { key: 'tighnari', name: '提纳里' },
70: { key: 'nilou', name: '妮露' },
71: { key: 'cyno', name: '赛诺' },
72: { key: 'candace', name: '坎蒂丝' }
}
await down('4', true)