mirror of
https://github.com/yoimiya-kokomi/miao-plugin.git
synced 2024-11-16 04:35:42 +00:00
部分架构底层升级,文件结构调整
This commit is contained in:
parent
90947380ee
commit
9686e9b277
@ -1,55 +1,20 @@
|
||||
import plugin from '../../../lib/plugins/plugin.js'
|
||||
import * as Miao from '../apps/index.js'
|
||||
import { render } from './render.js'
|
||||
import { checkAuth, getMysApi } from './mys.js'
|
||||
import fs from 'fs'
|
||||
import _puppeteer from './lib/puppeteer.js'
|
||||
import _plugin from './lib/plugin.js'
|
||||
|
||||
export class miao extends plugin {
|
||||
constructor () {
|
||||
let rule = {
|
||||
reg: '.+',
|
||||
fnc: 'dispatch'
|
||||
}
|
||||
super({
|
||||
name: 'miao-plugin',
|
||||
desc: '喵喵插件',
|
||||
event: 'message',
|
||||
priority: 50,
|
||||
rule: [rule]
|
||||
})
|
||||
Object.defineProperty(rule, 'log', {
|
||||
get: () => !!this.isDispatch
|
||||
})
|
||||
}
|
||||
|
||||
accept () {
|
||||
this.e.original_msg = this.e.original_msg || this.e.msg
|
||||
}
|
||||
|
||||
async dispatch (e) {
|
||||
let msg = e.original_msg || ''
|
||||
if (!msg) {
|
||||
return false
|
||||
}
|
||||
e.checkAuth = async function (cfg) {
|
||||
return await checkAuth(e, cfg)
|
||||
}
|
||||
e.getMysApi = async function (cfg) {
|
||||
return await getMysApi(e, cfg)
|
||||
}
|
||||
msg = msg.replace('#', '').trim()
|
||||
msg = '#' + msg
|
||||
for (let fn in Miao.rule) {
|
||||
let cfg = Miao.rule[fn]
|
||||
if (Miao[fn] && new RegExp(cfg.reg).test(msg)) {
|
||||
let ret = await Miao[fn](e, {
|
||||
render
|
||||
})
|
||||
if (ret === true) {
|
||||
this.isDispatch = true
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
const importV3 = async function (file, def, key = 'default') {
|
||||
if (fs.existsSync(process.cwd() + file)) {
|
||||
let obj = await import(`file://${process.cwd()}/${file}`)
|
||||
return obj[key] || def
|
||||
}
|
||||
return def
|
||||
}
|
||||
|
||||
let MysInfo = await importV3('/plugins/genshin/model/mys/mysInfo.js')
|
||||
let plugin = await importV3('lib/plugins/plugin.js', _plugin)
|
||||
let puppeteer = await importV3('/lib/puppeteer/puppeteer.js', _puppeteer)
|
||||
export {
|
||||
plugin,
|
||||
MysInfo,
|
||||
puppeteer
|
||||
}
|
||||
|
103
adapter/lib/plugin.js
Normal file
103
adapter/lib/plugin.js
Normal file
@ -0,0 +1,103 @@
|
||||
/*
|
||||
* V3版Yunzai plugin
|
||||
* */
|
||||
let stateArr = {}
|
||||
|
||||
export default class plugin {
|
||||
/**
|
||||
* @param name 插件名称
|
||||
* @param dsc 插件描述
|
||||
* @param event 执行事件,默认message
|
||||
* @param priority 优先级,数字越小优先级越高
|
||||
* @param rule.reg 命令正则
|
||||
* @param rule.fnc 命令执行方法
|
||||
* @param rule.event 执行事件,默认message
|
||||
* @param rule.log false时不显示执行日志
|
||||
* @param rule.permission 权限 master,owner,admin,all
|
||||
* @param task.name 定时任务名称
|
||||
* @param task.cron 定时任务cron表达式
|
||||
* @param task.fnc 定时任务方法名
|
||||
* @param task.log false时不显示执行日志
|
||||
*/
|
||||
constructor (data) {
|
||||
/** 插件名称 */
|
||||
this.name = data.name
|
||||
/** 插件描述 */
|
||||
this.dsc = data.dsc
|
||||
/** 监听事件,默认message https://oicqjs.github.io/oicq/#events */
|
||||
this.event = data.event || 'message'
|
||||
/** 优先级 */
|
||||
this.priority = data.priority || 5000
|
||||
/** 定时任务,可以是数组 */
|
||||
this.task = {
|
||||
/** 任务名 */
|
||||
name: '',
|
||||
/** 任务方法名 */
|
||||
fnc: data.task?.fnc || '',
|
||||
/** 任务cron表达式 */
|
||||
cron: data.task?.cron || ''
|
||||
}
|
||||
|
||||
/** 命令规则 */
|
||||
this.rule = data.rule || []
|
||||
}
|
||||
|
||||
/**
|
||||
* @param msg 发送的消息
|
||||
* @param quote 是否引用回复
|
||||
* @param data.recallMsg 群聊是否撤回消息,0-120秒,0不撤回
|
||||
* @param data.at 是否at用户
|
||||
*/
|
||||
reply (msg = '', quote = false, data = {}) {
|
||||
if (!this.e.reply || !msg) return false
|
||||
return this.e.reply(msg, quote, data)
|
||||
}
|
||||
|
||||
conKey (isGroup = false) {
|
||||
if (isGroup) {
|
||||
return `${this.name}.${this.e.group_id}`
|
||||
} else {
|
||||
return `${this.name}.${this.userId || this.e.user_id}`
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param type 执行方法
|
||||
* @param isGroup 是否群聊
|
||||
* @param time 操作时间,默认120秒
|
||||
*/
|
||||
setContext (type, isGroup = false, time = 120) {
|
||||
let key = this.conKey(isGroup)
|
||||
if (!stateArr[key]) stateArr[key] = {}
|
||||
stateArr[key][type] = this.e
|
||||
if (time) {
|
||||
/** 操作时间 */
|
||||
setTimeout(() => {
|
||||
if (stateArr[key][type]) {
|
||||
delete stateArr[key][type]
|
||||
this.e.reply('操作超时已取消', true)
|
||||
}
|
||||
}, time * 1000)
|
||||
}
|
||||
}
|
||||
|
||||
getContext () {
|
||||
let key = this.conKey()
|
||||
return stateArr[key]
|
||||
}
|
||||
|
||||
getContextGroup () {
|
||||
let key = this.conKey(true)
|
||||
return stateArr[key]
|
||||
}
|
||||
|
||||
/**
|
||||
* @param type 执行方法
|
||||
* @param isGroup 是否群聊
|
||||
*/
|
||||
finish (type, isGroup = false) {
|
||||
if (stateArr[this.conKey(isGroup)] && stateArr[this.conKey(isGroup)][type]) {
|
||||
delete stateArr[this.conKey(isGroup)][type]
|
||||
}
|
||||
}
|
||||
}
|
226
adapter/lib/puppeteer.js
Normal file
226
adapter/lib/puppeteer.js
Normal file
@ -0,0 +1,226 @@
|
||||
/*
|
||||
* V3版Yunzai puppeteer
|
||||
* */
|
||||
import template from 'art-template'
|
||||
import fs from 'fs'
|
||||
import lodash from 'lodash'
|
||||
import { segment } from 'oicq'
|
||||
|
||||
const _path = process.cwd()
|
||||
|
||||
let puppeteer = {}
|
||||
|
||||
let logger = global.logger || Bot.logger
|
||||
logger.green = logger.green || ((t) => t)
|
||||
|
||||
class Puppeteer {
|
||||
constructor () {
|
||||
this.browser = false
|
||||
this.lock = false
|
||||
this.shoting = []
|
||||
/** 截图数达到时重启浏览器 避免生成速度越来越慢 */
|
||||
this.restartNum = 400
|
||||
/** 截图次数 */
|
||||
this.renderNum = 0
|
||||
this.config = {
|
||||
headless: true,
|
||||
args: [
|
||||
'--disable-gpu',
|
||||
'--disable-dev-shm-usage',
|
||||
'--disable-setuid-sandbox',
|
||||
'--no-first-run',
|
||||
'--no-sandbox',
|
||||
'--no-zygote',
|
||||
'--single-process'
|
||||
]
|
||||
}
|
||||
|
||||
this.html = {}
|
||||
this.watcher = {}
|
||||
this.createDir('./data/html')
|
||||
}
|
||||
|
||||
async initXlsx () {
|
||||
if (!lodash.isEmpty(puppeteer)) return puppeteer
|
||||
|
||||
puppeteer = (await import('puppeteer')).default
|
||||
}
|
||||
|
||||
createDir (dir) {
|
||||
if (!fs.existsSync(dir)) {
|
||||
fs.mkdirSync(dir)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化chromium
|
||||
*/
|
||||
async browserInit () {
|
||||
await this.initXlsx()
|
||||
if (this.browser) return this.browser
|
||||
if (this.lock) return false
|
||||
this.lock = true
|
||||
|
||||
logger.mark('puppeteer Chromium 启动中。。')
|
||||
|
||||
/** 初始化puppeteer */
|
||||
this.browser = await puppeteer.launch(this.config).catch((err) => {
|
||||
logger.error(err.toString())
|
||||
if (String(err).includes('correct Chromium')) {
|
||||
logger.error('没有正确安装Chromium,可以尝试执行安装命令:node ./node_modules/puppeteer/install.js')
|
||||
}
|
||||
})
|
||||
|
||||
this.lock = false
|
||||
|
||||
if (!this.browser) {
|
||||
logger.error('puppeteer Chromium 启动失败')
|
||||
return false
|
||||
}
|
||||
|
||||
logger.mark('puppeteer Chromium 启动成功')
|
||||
|
||||
/** 监听Chromium实例是否断开 */
|
||||
this.browser.on('disconnected', (e) => {
|
||||
logger.error('Chromium实例关闭或崩溃!')
|
||||
this.browser = false
|
||||
})
|
||||
|
||||
return this.browser
|
||||
}
|
||||
|
||||
/**
|
||||
* `chromium` 截图
|
||||
* @param data 模板参数
|
||||
* @param data.tplFile 模板路径,必传
|
||||
* @param data.saveId 生成html名称,为空name代替
|
||||
* @param data.imgType screenshot参数,生成图片类型:jpeg,png
|
||||
* @param data.quality screenshot参数,图片质量 0-100,jpeg是可传,默认90
|
||||
* @param data.omitBackground screenshot参数,隐藏默认的白色背景,背景透明。默认不透明
|
||||
* @param data.path screenshot参数,截图保存路径。截图图片类型将从文件扩展名推断出来。如果是相对路径,则从当前路径解析。如果没有指定路径,图片将不会保存到硬盘。
|
||||
* @return oicq img
|
||||
*/
|
||||
async screenshot (name, data = {}) {
|
||||
if (!await this.browserInit()) {
|
||||
return false
|
||||
}
|
||||
|
||||
let savePath = this.dealTpl(name, data)
|
||||
if (!savePath) return false
|
||||
|
||||
let buff = ''
|
||||
let start = Date.now()
|
||||
try {
|
||||
this.shoting.push(name)
|
||||
|
||||
const page = await this.browser.newPage()
|
||||
await page.goto(`file://${_path}${lodash.trim(savePath, '.')}`)
|
||||
let body = await page.$('#container') || await page.$('body')
|
||||
|
||||
let randData = {
|
||||
// encoding: 'base64',
|
||||
type: data.imgType || 'jpeg',
|
||||
omitBackground: data.omitBackground || false,
|
||||
quality: data.quality || 90,
|
||||
path: data.path || ''
|
||||
}
|
||||
|
||||
if (data.imgType == 'png') delete randData.quality
|
||||
|
||||
buff = await body.screenshot(randData)
|
||||
|
||||
page.close().catch((err) => logger.error(err))
|
||||
|
||||
this.shoting.pop()
|
||||
} catch (error) {
|
||||
logger.error(`图片生成失败:${name}:${error}`)
|
||||
/** 关闭浏览器 */
|
||||
if (this.browser) {
|
||||
await this.browser.close().catch((err) => logger.error(err))
|
||||
}
|
||||
this.browser = false
|
||||
buff = ''
|
||||
return false
|
||||
}
|
||||
|
||||
if (!buff) {
|
||||
logger.error(`图片生成为空:${name}`)
|
||||
return false
|
||||
}
|
||||
|
||||
this.renderNum++
|
||||
|
||||
/** 计算图片大小 */
|
||||
let kb = (buff.length / 1024).toFixed(2) + 'kb'
|
||||
|
||||
logger.mark(`[图片生成][${name}][${this.renderNum}次] ${kb} ${logger.green(`${Date.now() - start}ms`)}`)
|
||||
|
||||
this.restart()
|
||||
|
||||
return segment.image(buff)
|
||||
}
|
||||
|
||||
/** 模板 */
|
||||
dealTpl (name, data) {
|
||||
let { tplFile, saveId = name } = data
|
||||
let savePath = `./data/html/${name}/${saveId}.html`
|
||||
|
||||
/** 读取html模板 */
|
||||
if (!this.html[tplFile]) {
|
||||
this.createDir(`./data/html/${name}`)
|
||||
|
||||
try {
|
||||
this.html[tplFile] = fs.readFileSync(tplFile, 'utf8')
|
||||
} catch (error) {
|
||||
logger.error(`加载html错误:${tplFile}`)
|
||||
return false
|
||||
}
|
||||
|
||||
this.watch(tplFile)
|
||||
}
|
||||
|
||||
data.resPath = `${_path}/resources/`
|
||||
|
||||
/** 替换模板 */
|
||||
let tmpHtml = template.render(this.html[tplFile], data)
|
||||
|
||||
/** 保存模板 */
|
||||
fs.writeFileSync(savePath, tmpHtml)
|
||||
|
||||
logger.debug(`[图片生成][使用模板] ${savePath}`)
|
||||
|
||||
return savePath
|
||||
}
|
||||
|
||||
/** 监听配置文件 */
|
||||
watch (tplFile) {
|
||||
/*
|
||||
if (this.watcher[tplFile]) return
|
||||
|
||||
const watcher = chokidar.watch(tplFile)
|
||||
watcher.on('change', path => {
|
||||
delete this.html[tplFile]
|
||||
logger.mark(`[修改html模板] ${tplFile}`)
|
||||
})
|
||||
|
||||
this.watcher[tplFile] = watcher
|
||||
*/
|
||||
}
|
||||
|
||||
/** 重启 */
|
||||
restart () {
|
||||
/** 截图超过重启数时,自动关闭重启浏览器,避免生成速度越来越慢 */
|
||||
if (this.renderNum % this.restartNum == 0) {
|
||||
if (this.shoting.length <= 0) {
|
||||
setTimeout(async () => {
|
||||
this.browser.removeAllListeners('disconnected')
|
||||
await this.browser.close().catch((err) => logger.error(err))
|
||||
this.browser = false
|
||||
logger.mark('puppeteer 关闭重启')
|
||||
}, 100)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default new Puppeteer()
|
@ -1,5 +1,5 @@
|
||||
import MysInfo from '../../genshin/model/mys/mysInfo.js'
|
||||
import lodash from 'lodash'
|
||||
import { MysInfo } from './index.js'
|
||||
|
||||
class User {
|
||||
constructor (cfg) {
|
||||
|
@ -1,21 +0,0 @@
|
||||
import lodash from 'lodash'
|
||||
import {Data} from '../components/index.js'
|
||||
import puppeteer from '../../../lib/puppeteer/puppeteer.js'
|
||||
|
||||
const plugin = 'miao-plugin'
|
||||
|
||||
const _path = process.cwd()
|
||||
|
||||
export async function render (app = '', tpl = '', data = {}, imgType = 'jpeg') {
|
||||
// 在data中保存plugin信息
|
||||
data._plugin = plugin
|
||||
|
||||
if (lodash.isUndefined(data._res_path)) {
|
||||
data._res_path = `../../../../../plugins/${plugin}/resources/`
|
||||
}
|
||||
Data.createDir(_path + '/data/', `html/${plugin}/${app}/${tpl}`)
|
||||
data.saveId = data.saveId || data.save_id || tpl
|
||||
data.tplFile = `./plugins/${plugin}/resources/${app}/${tpl}.html`
|
||||
data.pluResPath = data._res_path
|
||||
return await puppeteer.screenshot(`miao-plugin/${app}/${tpl}`, data)
|
||||
}
|
50
adapter/v3-entrance.js
Normal file
50
adapter/v3-entrance.js
Normal file
@ -0,0 +1,50 @@
|
||||
import * as Miao from '../apps/index.js'
|
||||
import { checkAuth, getMysApi } from './mys.js'
|
||||
import { plugin } from './index.js'
|
||||
|
||||
export class miao extends plugin {
|
||||
constructor () {
|
||||
let rule = {
|
||||
reg: '.+',
|
||||
fnc: 'dispatch'
|
||||
}
|
||||
super({
|
||||
name: 'miao-plugin',
|
||||
desc: '喵喵插件',
|
||||
event: 'message',
|
||||
priority: 50,
|
||||
rule: [rule]
|
||||
})
|
||||
Object.defineProperty(rule, 'log', {
|
||||
get: () => !!this.isDispatch
|
||||
})
|
||||
}
|
||||
|
||||
accept () {
|
||||
this.e.original_msg = this.e.original_msg || this.e.msg
|
||||
}
|
||||
|
||||
async dispatch (e) {
|
||||
let msg = e.original_msg || ''
|
||||
if (!msg) {
|
||||
return false
|
||||
}
|
||||
e.checkAuth = async function (cfg) {
|
||||
return await checkAuth(e, cfg)
|
||||
}
|
||||
e.getMysApi = async function (cfg) {
|
||||
return await getMysApi(e, cfg)
|
||||
}
|
||||
for (let fn in Miao.rule) {
|
||||
let cfg = Miao.rule[fn]
|
||||
if (Miao[fn] && new RegExp(cfg.reg).test(msg)) {
|
||||
let ret = await Miao[fn](e, {})
|
||||
if (ret === true) {
|
||||
this.isDispatch = true
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
@ -53,7 +53,7 @@ const checkAuth = async function (e) {
|
||||
})
|
||||
}
|
||||
|
||||
export async function sysCfg (e, { render }) {
|
||||
export async function sysCfg (e) {
|
||||
if (!await checkAuth(e)) {
|
||||
return true
|
||||
}
|
||||
@ -100,7 +100,7 @@ export async function sysCfg (e, { render }) {
|
||||
// 渲染图像
|
||||
return await Common.render('admin/index', {
|
||||
...cfg
|
||||
}, { e, render, scale: 1.4 })
|
||||
}, { e, scale: 1.4 })
|
||||
}
|
||||
|
||||
const getStatus = function (rote, def = true) {
|
||||
@ -200,7 +200,7 @@ export async function updateMiaoPlugin (e) {
|
||||
return true
|
||||
}
|
||||
|
||||
export async function profileCfg (e, { render }) {
|
||||
export async function profileCfg (e) {
|
||||
if (!await checkAuth(e)) {
|
||||
return true
|
||||
}
|
||||
@ -257,5 +257,5 @@ export async function profileCfg (e, { render }) {
|
||||
// 渲染图像
|
||||
return await Common.render('admin/profile', {
|
||||
...cfg
|
||||
}, { e, render, scale: 1.4 })
|
||||
}, { e, scale: 1.4 })
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ export { profileList } from './character/profile-list.js'
|
||||
export { profileStat } from './character/profile-stat.js'
|
||||
|
||||
// 查看当前角色
|
||||
export async function character (e, { render }) {
|
||||
export async function character (e) {
|
||||
let msg = e.original_msg || e.msg
|
||||
if (!msg) {
|
||||
return
|
||||
@ -95,7 +95,7 @@ export async function character (e, { render }) {
|
||||
}
|
||||
|
||||
if (mode === 'card') {
|
||||
return renderAvatar(e, char.name, render)
|
||||
return renderAvatar(e, char.name)
|
||||
}
|
||||
|
||||
let uid = await getTargetUid(e)
|
||||
@ -111,15 +111,15 @@ export async function character (e, { render }) {
|
||||
}
|
||||
|
||||
if (mode === 'profile' || mode === 'dmg') {
|
||||
return renderProfile(e, char, render, mode, { dmgIdx })
|
||||
return renderProfile(e, char, mode, { dmgIdx })
|
||||
} else if (mode === 'input') {
|
||||
await inputProfile(e, mode)
|
||||
return true
|
||||
} else if (mode === 'refresh') {
|
||||
await getProfile(e, { render })
|
||||
await getProfile(e)
|
||||
return true
|
||||
} else if (mode === 'artis') {
|
||||
return profileArtis(e, { render })
|
||||
return profileArtis(e)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ import { segment } from 'oicq'
|
||||
|
||||
let abbr = Character.getAbbr()
|
||||
|
||||
export async function renderAvatar (e, avatar, render, renderType = 'card') {
|
||||
export async function renderAvatar (e, avatar, renderType = 'card') {
|
||||
// 如果传递的是名字,则获取
|
||||
if (typeof (avatar) === 'string') {
|
||||
let char = Character.get(avatar)
|
||||
@ -45,11 +45,11 @@ export async function renderAvatar (e, avatar, render, renderType = 'card') {
|
||||
}
|
||||
}
|
||||
}
|
||||
return await renderCard(e, avatar, render, renderType)
|
||||
return await renderCard(e, avatar, renderType)
|
||||
}
|
||||
|
||||
// 渲染角色卡片
|
||||
async function renderCard (e, avatar, render, renderType = 'card') {
|
||||
async function renderCard (e, avatar, renderType = 'card') {
|
||||
let char = Character.get(avatar)
|
||||
|
||||
if (!char) {
|
||||
@ -69,7 +69,7 @@ async function renderCard (e, avatar, render, renderType = 'card') {
|
||||
e.reply(segment.image(process.cwd() + '/plugins/miao-plugin/resources/' + bg.img))
|
||||
} else {
|
||||
// 渲染图像
|
||||
let msgRes = await Common.render('character/card', {
|
||||
let msgRes = await Common.render('character/character-card', {
|
||||
save_id: uid,
|
||||
uid,
|
||||
talent,
|
||||
@ -79,7 +79,7 @@ async function renderCard (e, avatar, render, renderType = 'card') {
|
||||
custom: char.isCustom,
|
||||
...getCharacterData(avatar),
|
||||
ds: char.getData('name,id,title,desc')
|
||||
}, { e, render, scale: 1.6, retMsgId: true })
|
||||
}, { e, scale: 1.6, retMsgId: true })
|
||||
if (msgRes && msgRes.message_id) {
|
||||
// 如果消息发送成功,就将message_id和图片路径存起来,1小时过期
|
||||
await redis.set(`miao:original-picture:${msgRes.message_id}`, bg.img, { EX: 3600 })
|
||||
|
@ -34,7 +34,7 @@ const relationMap = {
|
||||
const relation = lodash.flatMap(relationMap, (d) => d.keyword)
|
||||
export const wifeReg = `^#?\\s*(${relation.join('|')})\\s*(设置|选择|指定|列表|查询|列表|是|是谁|照片|相片|图片|写真|图像)?\\s*([^\\d]*)\\s*(\\d*)$`
|
||||
|
||||
export async function wife (e, { render, User }) {
|
||||
export async function wife (e, { User }) {
|
||||
let msg = e.msg || ''
|
||||
if (!msg && !e.isPoke) return false
|
||||
|
||||
@ -104,10 +104,10 @@ export async function wife (e, { render, User }) {
|
||||
// 如果选择为全部,则从列表中随机选择一个
|
||||
avatarList = await getAvatarList(e, targetCfg.type, MysApi)
|
||||
let avatar = lodash.sample(avatarList)
|
||||
return renderAvatar(e, avatar, render, renderType)
|
||||
return renderAvatar(e, avatar, renderType)
|
||||
} else {
|
||||
// 如果指定过,则展示指定角色
|
||||
return renderAvatar(e, lodash.sample(wifeList), render, renderType)
|
||||
return renderAvatar(e, lodash.sample(wifeList), renderType)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -116,13 +116,13 @@ export async function wife (e, { render, User }) {
|
||||
avatarList = await getAvatarList(e, false, MysApi)
|
||||
if (avatarList && avatarList.length > 0) {
|
||||
avatar = lodash.sample(avatarList)
|
||||
return await renderAvatar(e, avatar, render, renderType)
|
||||
return await renderAvatar(e, avatar, renderType)
|
||||
}
|
||||
} else {
|
||||
avatarList = await getAvatarList(e, targetCfg.type, MysApi)
|
||||
if (avatarList && avatarList.length > 0) {
|
||||
avatar = lodash.sample(avatarList.slice(0, 5))
|
||||
return await renderAvatar(e, avatar, render, renderType)
|
||||
return await renderAvatar(e, avatar, renderType)
|
||||
}
|
||||
}
|
||||
e.reply('在当前米游社公开展示的角色中未能找到适合展示的角色..')
|
||||
|
@ -52,7 +52,7 @@ export async function uploadCharacterImg (e) {
|
||||
}
|
||||
|
||||
async function saveImages (e, name, imageMessages) {
|
||||
let imgMaxSize = e.groupConfig.imgMaxSize || 1
|
||||
let imgMaxSize = e?.groupConfig?.imgMaxSize || 5
|
||||
let pathSuffix = `character-img/${name}/upload`
|
||||
let path = resPath + pathSuffix
|
||||
|
||||
|
@ -10,11 +10,11 @@ import { Artifact } from '../../models/index.js'
|
||||
/*
|
||||
* 角色圣遗物面板
|
||||
* */
|
||||
export async function profileArtis (e, { render }) {
|
||||
export async function profileArtis (e) {
|
||||
let { uid, avatar } = e
|
||||
|
||||
let { profile, char, err } = await autoGetProfile(e, uid, avatar, async () => {
|
||||
await profileArtis(e, { render })
|
||||
await profileArtis(e)
|
||||
})
|
||||
|
||||
if (err) {
|
||||
@ -42,13 +42,13 @@ export async function profileArtis (e, { render }) {
|
||||
usefulMark,
|
||||
attrMap,
|
||||
charCfg
|
||||
}, { e, render, scale: 1.3 })
|
||||
}, { e, scale: 1.3 })
|
||||
}
|
||||
|
||||
/*
|
||||
* 圣遗物列表
|
||||
* */
|
||||
export async function profileArtisList (e, { render }) {
|
||||
export async function profileArtisList (e) {
|
||||
let uid = await getTargetUid(e)
|
||||
if (!uid) {
|
||||
return true
|
||||
@ -85,9 +85,9 @@ export async function profileArtisList (e, { render }) {
|
||||
artis = artis.slice(0, 28)
|
||||
|
||||
// 渲染图像
|
||||
return await Common.render('character/artis', {
|
||||
return await Common.render('character/artis-list', {
|
||||
save_id: uid,
|
||||
uid,
|
||||
artis
|
||||
}, { e, render, scale: 1.4 })
|
||||
}, { e, scale: 1.4 })
|
||||
}
|
||||
|
@ -133,7 +133,7 @@ export async function autoGetProfile (e, uid, avatar, callback) {
|
||||
}
|
||||
|
||||
let profile = Profile.get(uid, char.id)
|
||||
if (!profile) {
|
||||
if (!profile || !profile.hasData) {
|
||||
if (await refresh()) {
|
||||
return { err: true }
|
||||
} else {
|
||||
@ -179,7 +179,7 @@ export async function inputProfile (e) {
|
||||
/*
|
||||
* 面板数据更新
|
||||
* */
|
||||
export async function getProfile (e, { render }) {
|
||||
export async function getProfile (e) {
|
||||
let uid = await getTargetUid(e)
|
||||
if (!uid) {
|
||||
return true
|
||||
@ -205,7 +205,7 @@ export async function getProfile (e, { render }) {
|
||||
e.reply('获取角色面板数据失败,未能请求到角色数据。请确认角色已在游戏内橱窗展示,并开放了查看详情。设置完毕后请5分钟后再进行请求~')
|
||||
} else {
|
||||
e.newChar = ret
|
||||
return await profileList(e, { render })
|
||||
return await profileList(e)
|
||||
}
|
||||
}
|
||||
return true
|
||||
|
@ -2,7 +2,7 @@ import lodash from 'lodash'
|
||||
import { autoRefresh } from './profile-common.js'
|
||||
import { Common, Format, Profile } from '../../components/index.js'
|
||||
|
||||
export async function renderProfile (e, char, render, mode = 'profile', params = {}) {
|
||||
export async function renderProfile (e, char, mode = 'profile', params = {}) {
|
||||
let selfUser = await e.checkAuth({
|
||||
auth: 'self'
|
||||
})
|
||||
@ -21,7 +21,7 @@ export async function renderProfile (e, char, render, mode = 'profile', params =
|
||||
let refresh = async () => {
|
||||
let refreshRet = await autoRefresh(e)
|
||||
if (refreshRet) {
|
||||
await renderProfile(e, char, render, mode, params)
|
||||
await renderProfile(e, char, mode, params)
|
||||
}
|
||||
return refreshRet
|
||||
}
|
||||
@ -116,5 +116,5 @@ export async function renderProfile (e, char, render, mode = 'profile', params =
|
||||
talentMap: { a: '普攻', e: '战技', q: '爆发' },
|
||||
bodyClass: `char-${char.name}`,
|
||||
mode
|
||||
}, { e, render, scale: 1.6 })
|
||||
}, { e, scale: 1.6 })
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ import lodash from 'lodash'
|
||||
import { autoRefresh, getTargetUid } from './profile-common.js'
|
||||
import { Common, Profile } from '../../components/index.js'
|
||||
|
||||
export async function profileList (e, { render }) {
|
||||
export async function profileList (e) {
|
||||
let uid = await getTargetUid(e)
|
||||
if (!uid) {
|
||||
return true
|
||||
@ -38,7 +38,7 @@ export async function profileList (e, { render }) {
|
||||
|
||||
if (chars.length === 0) {
|
||||
if (await autoRefresh(e)) {
|
||||
await profileList(e, { render })
|
||||
await profileList(e)
|
||||
return true
|
||||
} else {
|
||||
e.reply('尚未获取任何角色数据')
|
||||
@ -61,5 +61,5 @@ export async function profileList (e, { render }) {
|
||||
servName,
|
||||
hasNew,
|
||||
msg
|
||||
}, { e, render, scale: 1.6 })
|
||||
}, { e, scale: 1.6 })
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ import lodash from 'lodash'
|
||||
import { Common, Profile, Data } from '../../components/index.js'
|
||||
import { Avatars } from '../../models/index.js'
|
||||
|
||||
export async function profileStat (e, { render }) {
|
||||
export async function profileStat (e) {
|
||||
// 缓存时间,单位小时
|
||||
|
||||
let msg = e.msg.replace('#', '').trim()
|
||||
@ -68,5 +68,5 @@ export async function profileStat (e, { render }) {
|
||||
isSelf: e.isSelf,
|
||||
talentNotice,
|
||||
elem: 'hydro'
|
||||
}, { e, render, scale: 1.8 })
|
||||
}, { e, scale: 1.8 })
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ import { Cfg, Version, Common } from '../components/index.js'
|
||||
const _path = process.cwd()
|
||||
const helpPath = `${_path}/plugins/miao-plugin/resources/help`
|
||||
|
||||
export async function help (e, { render }) {
|
||||
export async function help (e) {
|
||||
if (!/喵喵/.test(e.msg) && !Cfg.get('sys.help', false)) {
|
||||
return false
|
||||
}
|
||||
@ -58,13 +58,13 @@ export async function help (e, { render }) {
|
||||
helpCfg,
|
||||
helpGroup,
|
||||
element: 'default'
|
||||
}, { e, render, scale: 1.2 })
|
||||
}, { e, scale: 1.2 })
|
||||
}
|
||||
|
||||
export async function versionInfo (e, { render }) {
|
||||
export async function versionInfo (e) {
|
||||
return await Common.render('help/version-info', {
|
||||
currentVersion: Version.version,
|
||||
changelogs: Version.changelogs,
|
||||
elem: 'cryo'
|
||||
}, { e, render, scale: 1.2 })
|
||||
}, { e, scale: 1.2 })
|
||||
}
|
||||
|
16
apps/stat.js
16
apps/stat.js
@ -8,7 +8,7 @@ import { Cfg, Common } from '../components/index.js'
|
||||
import { Abyss, Avatars, Character } from '../models/index.js'
|
||||
import HutaoApi from './stat/HutaoApi.js'
|
||||
|
||||
export async function consStat (e, { render }) {
|
||||
export async function consStat (e) {
|
||||
if (Cfg.isDisable(e, 'wiki.stat')) {
|
||||
return
|
||||
}
|
||||
@ -87,10 +87,10 @@ export async function consStat (e, { render }) {
|
||||
pct: function (num) {
|
||||
return (num * 100).toFixed(2)
|
||||
}
|
||||
}, { e, render, scale: 1.5 })
|
||||
}, { e, scale: 1.5 })
|
||||
}
|
||||
|
||||
export async function abyssPct (e, { render }) {
|
||||
export async function abyssPct (e) {
|
||||
if (Cfg.isDisable(e, 'wiki.stat')) {
|
||||
return
|
||||
}
|
||||
@ -171,7 +171,7 @@ export async function abyssPct (e, { render }) {
|
||||
modeName,
|
||||
totalCount: overview?.data?.collectedPlayerCount || 0,
|
||||
lastUpdate: abyssData.lastUpdate
|
||||
}, { e, render, scale: 1.5 })
|
||||
}, { e, scale: 1.5 })
|
||||
}
|
||||
|
||||
async function getTalentData (e, isUpdate = false) {
|
||||
@ -202,7 +202,7 @@ async function getTalentData (e, isUpdate = false) {
|
||||
return false
|
||||
}
|
||||
|
||||
export async function abyssTeam (e, { render }) {
|
||||
export async function abyssTeam (e) {
|
||||
if (Common.todoV3(e)) {
|
||||
return true
|
||||
}
|
||||
@ -393,10 +393,10 @@ export async function abyssTeam (e, { render }) {
|
||||
return await Common.render('stat/abyss-team', {
|
||||
teams: ret,
|
||||
avatars: avatarMap
|
||||
}, { e, render, scale: 1.5 })
|
||||
}, { e, scale: 1.5 })
|
||||
}
|
||||
|
||||
export async function uploadData (e, { render }) {
|
||||
export async function uploadData (e) {
|
||||
let isMatch = /^#(喵喵|上传)深渊(数据)?$/.test(e.original_msg || e.msg || '')
|
||||
if (!Cfg.get('wiki.abyss', false) && !isMatch) {
|
||||
return false
|
||||
@ -498,7 +498,7 @@ export async function uploadData (e, { render }) {
|
||||
save_id: uid,
|
||||
totalCount: overview?.collectedPlayerCount || 0,
|
||||
uid
|
||||
}, { e, render, scale: 1.8 })
|
||||
}, { e, scale: 1.8 })
|
||||
} else {
|
||||
e.reply('暂未获得本期深渊挑战数据...')
|
||||
return true
|
||||
|
@ -11,7 +11,7 @@ let action = {
|
||||
}
|
||||
}
|
||||
|
||||
export async function wiki (e, { render }) {
|
||||
export async function wiki (e) {
|
||||
if (!e.msg) {
|
||||
return false
|
||||
}
|
||||
@ -62,7 +62,7 @@ export async function wiki (e, { render }) {
|
||||
mode,
|
||||
line: getLineData(char),
|
||||
_char: `/meta/character/${char.name}/`
|
||||
}, { e, render, scale: 1 })
|
||||
}, { e, scale: 1 })
|
||||
}
|
||||
|
||||
const getLineData = function (data) {
|
||||
@ -77,7 +77,7 @@ const getLineData = function (data) {
|
||||
return ret
|
||||
}
|
||||
|
||||
export async function calendar (e, { render }) {
|
||||
export async function calendar (e) {
|
||||
let calData = await Calendar.get()
|
||||
let mode = 'calendar'
|
||||
if (/(日历列表|活动)$/.test(e.msg)) {
|
||||
@ -87,5 +87,5 @@ export async function calendar (e, { render }) {
|
||||
return await Common.render('wiki/calendar', {
|
||||
...calData,
|
||||
displayMode: mode
|
||||
}, { e, render, scale: 1.1 })
|
||||
}, { e, scale: 1.1 })
|
||||
}
|
||||
|
@ -1,13 +1,23 @@
|
||||
import Cfg from './Cfg.js'
|
||||
import { Version } from './index.js'
|
||||
import { segment } from 'oicq'
|
||||
import { Data, Version } from './index.js'
|
||||
import { puppeteer } from '../adapter/index.js'
|
||||
|
||||
const plugin = 'miao-plugin'
|
||||
const _path = process.cwd()
|
||||
|
||||
export const render = async function (path, params, cfg) {
|
||||
let paths = path.split('/')
|
||||
let { render, e } = cfg
|
||||
let [app, tpl] = path.split('/')
|
||||
let { e } = cfg
|
||||
let layoutPath = process.cwd() + '/plugins/miao-plugin/resources/common/layout/'
|
||||
let base64 = await render(paths[0], paths[1], {
|
||||
let resPath = `../../../../../plugins/${plugin}/resources/`
|
||||
Data.createDir(_path + '/data/', `html/${plugin}/${app}/${tpl}`)
|
||||
let data = {
|
||||
...params,
|
||||
_plugin: plugin,
|
||||
saveId: params.saveId || params.save_id || tpl,
|
||||
tplFile: `./plugins/${plugin}/resources/${app}/${tpl}.html`,
|
||||
pluResPath: resPath,
|
||||
_res_path: resPath,
|
||||
_layout_path: layoutPath,
|
||||
_tpl_path: process.cwd() + '/plugins/miao-plugin/resources/common/tpl/',
|
||||
defaultLayout: layoutPath + 'default.html',
|
||||
@ -16,11 +26,11 @@ export const render = async function (path, params, cfg) {
|
||||
scale: Cfg.scale(cfg.scale || 1),
|
||||
copyright: `Created By Yunzai-Bot<span class="version">${Version.yunzai}</span> & Miao-Plugin<span class="version">${Version.version}</span>`
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
let base64 = await puppeteer.screenshot(`miao-plugin/${app}/${tpl}`, data)
|
||||
let ret = true
|
||||
if (base64) {
|
||||
ret = Version.isV3 ? await e.reply(base64) : await e.reply(segment.image(`base64://${base64}`))
|
||||
ret = await e.reply(base64)
|
||||
}
|
||||
return cfg.retMsgId ? ret : true
|
||||
}
|
||||
|
@ -75,7 +75,7 @@ export const characters = {
|
||||
|
||||
// 以下为Miao新增自定义角色
|
||||
paimon: ['派蒙', '应急食物', '应急食品', '吉祥物', '宠物', '外置器官', '会说话的动物', '矮堇瓜', '飞行矮堇瓜', '最好的伙伴'],
|
||||
sb: ['散兵', '国崩', '雷电国崩', '大炮', '雷电大炮', '雷大炮', '伞兵', '斯卡拉姆齐'],
|
||||
sanbing: ['散兵', '国崩', '雷电国崩', '大炮', '雷电大炮', '雷大炮', '伞兵', '斯卡拉姆齐'],
|
||||
nvshi: ['女士', '炽热的炎之魔女', '炎之魔女', '罗莎琳'],
|
||||
baizhu: ['白术', '长生'],
|
||||
yaoyao: ['瑶瑶', '遥遥', '遥遥无期'],
|
||||
|
5
index.js
5
index.js
@ -1,14 +1,13 @@
|
||||
// 适配V3 Yunzai,将index.js移至app/index.js
|
||||
import { Data, Version } from './components/index.js'
|
||||
|
||||
export * from './apps/index.js'
|
||||
let index = { miao: {} }
|
||||
if (Version.isV3) {
|
||||
index = await Data.importModule('/plugins/miao-plugin/adapter', 'index.js')
|
||||
index = await Data.importModule('/plugins/miao-plugin/adapter', 'v3-entrance.js')
|
||||
}
|
||||
export const miao = index.miao || {}
|
||||
if (Bot?.logger?.info) {
|
||||
Bot.logger.info(`---------^_^---------`)
|
||||
Bot.logger.info('---------^_^---------')
|
||||
Bot.logger.info(`喵喵插件${Version.version}初始化~`)
|
||||
} else {
|
||||
console.log(`喵喵插件${Version.version}初始化~`)
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { attrMap }
|
||||
from '../resources/meta/reliquaries/reliquaries-mark-new.js'
|
||||
import { attrMap } from '../resources/meta/reliquaries/artis-mark.js'
|
||||
import lodash from 'lodash'
|
||||
import { Data } from '../components/index.js'
|
||||
|
||||
|
@ -6,7 +6,7 @@ import Base from './Base.js'
|
||||
import { Artifact, Character } from './index.js'
|
||||
import { Format } from '../components/index.js'
|
||||
import ArtisMark from './profile-lib/ArtisMark.js'
|
||||
import { attrMap, attrValue, usefulAttr } from '../resources/meta/reliquaries/reliquaries-mark-new.js'
|
||||
import { attrMap, attrValue, usefulAttr } from '../resources/meta/reliquaries/artis-mark.js'
|
||||
|
||||
let charCfg = {}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
import lodash from 'lodash'
|
||||
import { Format } from '../../components/index.js'
|
||||
import { attrNameMap, mainAttr, subAttr } from '../../resources/meta/reliquaries/reliquaries-mark-new.js'
|
||||
import { attrNameMap, mainAttr, subAttr } from '../../resources/meta/reliquaries/artis-mark.js'
|
||||
|
||||
let ArtisMark = {
|
||||
formatAttr (ds) {
|
||||
|
@ -1,144 +0,0 @@
|
||||
import lodash from 'lodash'
|
||||
import { Character } from '../index.js'
|
||||
import { eleBaseDmg, eleMap, } from './calc-meta.js'
|
||||
import Mastery from './Mastery.js'
|
||||
|
||||
let Calc = {
|
||||
getDmgFn ({ ds, attr, profile, enemyLv, showDetail = false }) {
|
||||
let { calc } = ds
|
||||
|
||||
let dmgFn = function (pctNum = 0, talent = false, ele = false, basicNum = 0, mode = 'talent') {
|
||||
let { atk, dmg, phy, cdmg, cpct } = attr
|
||||
// 攻击区
|
||||
let atkNum = calc(atk)
|
||||
|
||||
// 倍率独立乘区
|
||||
let multiNum = attr.multi / 100
|
||||
|
||||
// 增伤区
|
||||
let dmgNum = (1 + dmg.base / 100 + dmg.plus / 100)
|
||||
|
||||
if (ele === 'phy') {
|
||||
dmgNum = (1 + phy.base / 100 + phy.plus / 100)
|
||||
}
|
||||
|
||||
// console.log({ base: Format.comma(dmg.base, 2), plus: Format.comma(dmg.plus, 2) })
|
||||
|
||||
let cpctNum = cpct.base / 100 + cpct.plus / 100
|
||||
|
||||
// 爆伤区
|
||||
let cdmgNum = cdmg.base / 100 + cdmg.plus / 100
|
||||
|
||||
let enemyDef = attr.enemy.def / 100
|
||||
let enemyIgnore = attr.enemy.ignore / 100
|
||||
|
||||
let plusNum = 0
|
||||
|
||||
if (talent && attr[talent]) {
|
||||
pctNum = pctNum / 100
|
||||
|
||||
let ds = attr[talent]
|
||||
|
||||
pctNum += ds.pct / 100
|
||||
dmgNum += ds.dmg / 100
|
||||
cpctNum += ds.cpct / 100
|
||||
cdmgNum += ds.cdmg / 100
|
||||
enemyDef += ds.def / 100
|
||||
enemyIgnore += ds.ignore / 100
|
||||
multiNum += ds.multi / 100
|
||||
plusNum += ds.plus
|
||||
}
|
||||
|
||||
// 防御区
|
||||
let lv = profile.lv || profile.level
|
||||
let defNum = (lv + 100) / ((lv + 100) + (enemyLv + 100) * (1 - enemyDef) * (1 - enemyIgnore))
|
||||
|
||||
// 抗性区
|
||||
let kx = attr.kx
|
||||
if (talent === 'fy') {
|
||||
kx = attr.fykx
|
||||
}
|
||||
kx = 10 - (kx || 0)
|
||||
let kNum = 0.9
|
||||
if (kx >= 0) {
|
||||
kNum = (100 - kx) / 100
|
||||
} else {
|
||||
kNum = 1 - kx / 200
|
||||
}
|
||||
|
||||
// 反应区
|
||||
let eleNum = 1
|
||||
let eleBase = 0
|
||||
|
||||
if (ele === 'ks' || ele === 'gd') {
|
||||
eleBase = eleBaseDmg[lv] || 0
|
||||
}
|
||||
|
||||
if (ele === 'phy') {
|
||||
// do nothing
|
||||
} else if (ele) {
|
||||
eleNum = Mastery.getBasePct(ele, attr.element)
|
||||
|
||||
if (attr[ele]) {
|
||||
eleNum = eleNum * (1 + attr[ele] / 100)
|
||||
}
|
||||
}
|
||||
|
||||
cpctNum = Math.max(0, Math.min(1, cpctNum))
|
||||
if (cpctNum === 0) {
|
||||
cdmgNum = 0
|
||||
}
|
||||
|
||||
let ret = {}
|
||||
if (mode === 'basic') {
|
||||
ret = {
|
||||
dmg: basicNum * dmgNum * (1 + cdmgNum) * defNum * kNum * eleNum,
|
||||
avg: basicNum * dmgNum * (1 + cpctNum * cdmgNum) * defNum * kNum * eleNum
|
||||
}
|
||||
} else if (eleBase) {
|
||||
ret = {
|
||||
avg: eleBase * kNum * eleNum
|
||||
}
|
||||
} else {
|
||||
// 计算最终伤害
|
||||
ret = {
|
||||
dmg: (atkNum * pctNum * (1 + multiNum) + plusNum) * dmgNum * (1 + cdmgNum) * defNum * kNum * eleNum,
|
||||
avg: (atkNum * pctNum * (1 + multiNum) + plusNum) * dmgNum * (1 + cpctNum * cdmgNum) * defNum * kNum * eleNum
|
||||
}
|
||||
}
|
||||
|
||||
if (showDetail) {
|
||||
console.log(attr, { atkNum, pctNum, multiNum, plusNum, dmgNum, cpctNum, cdmgNum, defNum, eleNum, kNum }, ret)
|
||||
}
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
dmgFn.basic = function (basicNum = 0, talent = false, ele = false) {
|
||||
return dmgFn(0, talent, ele, basicNum, 'basic')
|
||||
}
|
||||
|
||||
dmgFn.heal = function (num) {
|
||||
if (showDetail) {
|
||||
console.log(num, calc(attr.heal), attr.heal.inc)
|
||||
}
|
||||
return {
|
||||
avg: num * (1 + calc(attr.heal) / 100 + attr.heal.inc / 100)
|
||||
}
|
||||
}
|
||||
|
||||
dmgFn.shield = function (num) {
|
||||
return {
|
||||
avg: num * (calc(attr.shield) / 100) * (attr.shield.inc / 100)
|
||||
}
|
||||
}
|
||||
dmgFn.ks = function () {
|
||||
return dmgFn(0, 'fy', 'ks')
|
||||
}
|
||||
|
||||
return dmgFn
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default Calc
|
@ -3,7 +3,7 @@
|
||||
* */
|
||||
import { attrMap, eleMap } from './calc-meta.js'
|
||||
import lodash from 'lodash'
|
||||
import Mastery from './Mastery.js'
|
||||
import DmgMastery from './DmgMastery.js'
|
||||
import { Format } from '../../components/index.js'
|
||||
|
||||
let DmgAttr = {
|
||||
@ -142,8 +142,7 @@ let DmgAttr = {
|
||||
// let masteryNum = 2.78 * mastery / (mastery + 1400) * 100;
|
||||
buff.data = buff.data || {}
|
||||
lodash.forEach(buff.mastery.split(','), (key) => {
|
||||
buff.data[key] = Mastery.getMultiple(key, mastery)
|
||||
// buff.data[key] = masteryNum;
|
||||
buff.data[key] = DmgMastery.getMultiple(key, mastery)
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
* 伤害计算 - 计算伤害
|
||||
* */
|
||||
import { eleBaseDmg } from './calc-meta.js'
|
||||
import Mastery from './Mastery.js'
|
||||
import DmgMastery from './DmgMastery.js'
|
||||
|
||||
let DmgCalc = {
|
||||
calcRet (fnArgs = {}, data = {}) {
|
||||
@ -88,7 +88,7 @@ let DmgCalc = {
|
||||
if (ele === 'phy') {
|
||||
// do nothing
|
||||
} else if (ele) {
|
||||
eleNum = Mastery.getBasePct(ele, attr.element)
|
||||
eleNum = DmgMastery.getBasePct(ele, attr.element)
|
||||
|
||||
if (attr[ele]) {
|
||||
eleNum = eleNum * (1 + attr[ele] / 100)
|
||||
|
@ -1,10 +1,6 @@
|
||||
import { erType } from './calc-meta.js'
|
||||
|
||||
let Mastery = {
|
||||
|
||||
getType () {
|
||||
|
||||
},
|
||||
let DmgMastery = {
|
||||
getMultiple (type = 'zf', mastery = 0) {
|
||||
let typeCfg = erType[type]
|
||||
if (typeCfg.type === 'pct') {
|
||||
@ -22,4 +18,4 @@ let Mastery = {
|
||||
return 1
|
||||
}
|
||||
}
|
||||
export default Mastery
|
||||
export default DmgMastery
|
@ -63,7 +63,6 @@ body {
|
||||
color: #495366;
|
||||
font-weight: bold;
|
||||
border-radius: 0 16px 16px 0;
|
||||
font-family: Number, "微软雅黑", sans-serif;
|
||||
}
|
||||
.cfg-status.status-off {
|
||||
color: #a95151;
|
||||
@ -73,4 +72,4 @@ body {
|
||||
color: #cbc4be;
|
||||
margin: 5px 0 5px 20px;
|
||||
}
|
||||
/*# sourceMappingURL=index.less.map */
|
||||
/*# sourceMappingURL=index.css.map */
|
@ -76,7 +76,6 @@ body {
|
||||
color: #495366;
|
||||
font-weight: bold;
|
||||
border-radius: 0 16px 16px 0;
|
||||
font-family: Number, "微软雅黑", sans-serif;
|
||||
}
|
||||
|
||||
.cfg-status.status-off {
|
||||
|
@ -32,4 +32,4 @@
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
}
|
||||
/*# sourceMappingURL=artis.css.map */
|
||||
/*# sourceMappingURL=artis-list.css.map */
|
@ -2,7 +2,7 @@
|
||||
|
||||
{{block 'css'}}
|
||||
<link rel="stylesheet" type="text/css" href="{{_res_path}}/character/profile-detail.css"/>
|
||||
<link rel="stylesheet" type="text/css" href="{{_res_path}}/character/artis.css"/>
|
||||
<link rel="stylesheet" type="text/css" href="{{_res_path}}/character/artis-list.css"/>
|
||||
{{/block}}
|
||||
|
||||
{{block 'main'}}
|
@ -434,4 +434,4 @@ body.bottom_mode {
|
||||
.bottom_mode .no-info {
|
||||
bottom: 25px;
|
||||
}
|
||||
/*# sourceMappingURL=card.css.map */
|
||||
/*# sourceMappingURL=character-card.css.map */
|
@ -4,7 +4,7 @@
|
||||
<meta http-equiv="content-type" content="text/html;charset=utf-8"/>
|
||||
<link rel="shortcut icon" href="#"/>
|
||||
<link rel="stylesheet" type="text/css" href="{{_res_path}}/common/common.css?v=1.0"/>
|
||||
<link rel="stylesheet" type="text/css" href="{{_res_path}}/character/card.css?v=1.0"/>
|
||||
<link rel="stylesheet" type="text/css" href="{{_res_path}}/character/character-card.css?v=1.0"/>
|
||||
</head>
|
||||
<body class="{{bg.mode}}_mode" {{sys.scale}}>
|
||||
|
@ -487,7 +487,6 @@ body.bottom_mode {
|
||||
|
||||
.copyright {
|
||||
position: absolute;
|
||||
//font-family: Number, YS;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
@ -265,7 +265,7 @@
|
||||
font-family: Number, "汉仪文黑-65W", YS, PingFangSC-Medium, "PingFang SC", sans-serif;
|
||||
}
|
||||
.font-NZBZ {
|
||||
font-family: Number, "印品南征北战NZBZ体", NZBZ, PingFangSC-Medium, "PingFang SC", sans-serif;
|
||||
font-family: Number, "印品南征北战NZBZ体", NZBZ, "汉仪文黑-65W", YS, PingFangSC-Medium, "PingFang SC", sans-serif;
|
||||
}
|
||||
.profile {
|
||||
position: relative;
|
||||
@ -302,7 +302,7 @@
|
||||
}
|
||||
.profile .char-name {
|
||||
font-size: 50px;
|
||||
font-family: Number, "印品南征北战NZBZ体", NZBZ, PingFangSC-Medium, "PingFang SC", sans-serif;
|
||||
font-family: Number, "印品南征北战NZBZ体", NZBZ, "汉仪文黑-65W", YS, PingFangSC-Medium, "PingFang SC", sans-serif;
|
||||
text-shadow: 0 0 3px #000, 2px 2px 4px rgba(0, 0, 0, 0.7);
|
||||
text-align: right;
|
||||
}
|
||||
|
@ -95,7 +95,6 @@
|
||||
&.val {
|
||||
text-align: right;
|
||||
padding-right: 10px;
|
||||
//font-family: Number;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -11,7 +11,6 @@ body {
|
||||
}
|
||||
|
||||
.label {
|
||||
//font-family: Number, "微软雅黑", sans-serif;
|
||||
}
|
||||
|
||||
.head-box {
|
||||
|
@ -24,3 +24,8 @@ export const buffs = [{
|
||||
dmg: 15
|
||||
}
|
||||
}, 'zf']
|
||||
|
||||
export const artisSect = function ({ attr, calc }) {
|
||||
let test = calc(attr.cpct) * 2 + calc(attr.cdmg) + calc(attr.dmg)
|
||||
return test > 150 ? '暴力' : false
|
||||
}
|
||||
|
@ -1,108 +0,0 @@
|
||||
export const attrMark = {
|
||||
暴击率: 2,
|
||||
暴击伤害: 1,
|
||||
元素精通: 0.25,
|
||||
大攻击: 1,
|
||||
大生命: 0.86,
|
||||
大防御: 0.7,
|
||||
小攻击: 0.12,
|
||||
小生命: 0.014,
|
||||
小防御: 0.18,
|
||||
充能效率: 0.65
|
||||
}
|
||||
|
||||
export const maxMark = {
|
||||
暴击率: 46.6,
|
||||
暴击伤害: 46.6,
|
||||
元素精通: 35,
|
||||
大攻击: 35,
|
||||
大生命: 30.1,
|
||||
大防御: 30.59,
|
||||
小攻击: 14.04,
|
||||
小生命: 25.1,
|
||||
小防御: 25.02,
|
||||
充能效率: 25.2
|
||||
}
|
||||
|
||||
export const attrMap = {
|
||||
atk: {
|
||||
title: '攻击力',
|
||||
attr: '小攻击,大攻击'
|
||||
},
|
||||
def: {
|
||||
title: '防御力',
|
||||
attr: '小防御,大防御'
|
||||
},
|
||||
hp: {
|
||||
title: '生命值',
|
||||
attr: '小生命,大生命'
|
||||
},
|
||||
cRate: {
|
||||
title: '暴击率',
|
||||
attr: '暴击率'
|
||||
},
|
||||
cDmg: {
|
||||
title: '暴击伤害',
|
||||
attr: '暴击伤害'
|
||||
},
|
||||
mastery: {
|
||||
title: '元素精通',
|
||||
attr: '元素精通'
|
||||
},
|
||||
recharge: {
|
||||
title: '充能效率',
|
||||
attr: '充能效率'
|
||||
}
|
||||
}
|
||||
|
||||
export const usefulAttr = {
|
||||
神里绫人: 'hp,atk,cRate,cDmg,mastery',
|
||||
八重神子: 'atk,cRate,cDmg,mastery,',
|
||||
申鹤: 'atk,recharge',
|
||||
云堇: 'def,recharge',
|
||||
荒泷一斗: 'def,cRate,cDmg',
|
||||
五郎: 'def,recharge',
|
||||
班尼特: 'hp,atk,cRate,cDmg,recharge',
|
||||
枫原万叶: 'mastery,cRate,cDmg,recharge',
|
||||
雷电将军: 'atk,cRate,cDmg,recharge',
|
||||
行秋: 'atk,cRate,cDmg,recharge',
|
||||
钟离: 'hp,atk,cRate,cDmg,recharge',
|
||||
神里绫华: 'atk,cRate,cDmg',
|
||||
香菱: 'atk,cRate,cDmg,recharge,mastery',
|
||||
胡桃: 'hp,cRate,cDmg,mastery',
|
||||
甘雨: 'atk,cRate,cDmg,mastery',
|
||||
温迪: 'mastery,cRate,cDmg,recharge',
|
||||
珊瑚宫心海: 'hp,recharge',
|
||||
莫娜: 'mastery,cRate,cDmg,recharge',
|
||||
阿贝多: 'def,cRate,cDmg',
|
||||
迪奥娜: 'hp,recharge',
|
||||
优菈: 'atk,cRate,cDmg',
|
||||
达达利亚: 'atk,cRate,cDmg,mastery',
|
||||
魈: 'atk,cRate,cDmg',
|
||||
宵宫: 'atk,cRate,cDmg,mastery',
|
||||
九条裟罗: 'atk,cRate,cDmg,recharge',
|
||||
琴: 'atk,cRate,cDmg,recharge',
|
||||
菲谢尔: 'atk,cRate,cDmg',
|
||||
罗莎莉亚: 'atk,cRate,cDmg',
|
||||
可莉: 'atk,cRate,cDmg',
|
||||
凝光: 'atk,cRate,cDmg',
|
||||
北斗: 'atk,cRate,cDmg',
|
||||
刻晴: 'atk,cRate,cDmg',
|
||||
托马: 'hp,recharge',
|
||||
迪卢克: 'atk,cRate,cDmg,mastery',
|
||||
芭芭拉: 'hp,recharge',
|
||||
诺艾尔: 'def,cRate,cDmg',
|
||||
旅行者: 'atk,cRate,cDmg',
|
||||
重云: 'atk,cRate,cDmg',
|
||||
七七: 'atk,cRate,cDmg,recharge',
|
||||
凯亚: 'atk,cRate,cDmg',
|
||||
烟绯: 'atk,cRate,cDmg,mastery',
|
||||
早柚: 'mastery,recharge',
|
||||
安柏: 'atk,cRate,cDmg,mastery',
|
||||
丽莎: 'atk,cRate,cDmg',
|
||||
埃洛伊: 'atk,cRate,cDmg',
|
||||
辛焱: 'atk,cRate,cDmg',
|
||||
砂糖: 'mastery,recharge',
|
||||
雷泽: 'atk,cRate,cDmg',
|
||||
夜兰: 'hp,cRate,cDmg,recharge'
|
||||
}
|
@ -91,7 +91,6 @@
|
||||
border-radius: 3px;
|
||||
padding: 1px 5px;
|
||||
background: rgb(0 0 0 / 50%);
|
||||
//font-family: Number;
|
||||
}
|
||||
|
||||
.card-list .card .name,
|
||||
|
@ -15,7 +15,6 @@ body {
|
||||
background: url("./imgs/bg1.png") top left no-repeat #2a3860;
|
||||
background-size: contain;
|
||||
width: 600px;
|
||||
//font-family: Number, YS2;
|
||||
}
|
||||
|
||||
.container {
|
||||
|
@ -1,129 +1,135 @@
|
||||
import fs from "fs";
|
||||
import cheerio from "cheerio";
|
||||
import lodash from "lodash";
|
||||
import fetch from "node-fetch";
|
||||
import { roleId, abbr } from "../../../config/genshin/roleId.js";
|
||||
import fs from 'fs'
|
||||
import cheerio from 'cheerio'
|
||||
import lodash from 'lodash'
|
||||
import fetch from 'node-fetch'
|
||||
import { roleId, abbr } from '../../../config/genshin/roleId.js'
|
||||
|
||||
const _path = process.cwd();
|
||||
let roleIdMap = {};
|
||||
const _path = process.cwd()
|
||||
let roleIdMap = {}
|
||||
lodash.forEach(roleId, (names, id) => {
|
||||
roleIdMap[names[0]] = id;
|
||||
});
|
||||
roleIdMap[names[0]] = id
|
||||
})
|
||||
|
||||
function getBasic($, name) {
|
||||
function getBasic ($, name) {
|
||||
let ret = {}
|
||||
|
||||
if (name) {
|
||||
ret.name = name;
|
||||
ret.name = name
|
||||
} else {
|
||||
// 采集基础信息
|
||||
ret.name = $("#scroll_card_item").next("table").find("tr:first td:eq(1)").text();
|
||||
ret.name = $('#scroll_card_item').next('table').find('tr:first td:eq(1)').text()
|
||||
}
|
||||
ret.abbr = abbr[ret.name] || ret.name;
|
||||
ret.id = roleIdMap[ret.name] || '';
|
||||
ret.abbr = abbr[ret.name] || ret.name
|
||||
ret.id = roleIdMap[ret.name] || ''
|
||||
|
||||
let basic = $(".data_cont_wrapper table:first");
|
||||
let basic = $('.data_cont_wrapper table:first')
|
||||
console.log('basic', basic)
|
||||
let title = function (title) {
|
||||
return basic.find(`td:contains('${title}')`).next("td").text();
|
||||
return basic.find(`td:contains('${title}')`).next('td').text()
|
||||
}
|
||||
ret.title = title("Title");
|
||||
ret.star = basic.find(`td:contains('Rarity')`).next("td").find(".sea_char_stars_wrap").length;
|
||||
let elem = basic.find(`td:contains('Element')`).next("td").find("img").attr("data-src");
|
||||
ret.title = title('Title')
|
||||
ret.star = basic.find('td:contains(\'Rarity\')').next('td').find('.sea_char_stars_wrap').length
|
||||
let elem = basic.find('td:contains(\'Element\')').next('td').find('img').attr('data-src')
|
||||
|
||||
let elemRet = /\/([^\/]*)_35/.exec(elem);
|
||||
let elemRet = /\/([^/]*)_35/.exec(elem)
|
||||
if (elemRet) {
|
||||
ret.elem = elemRet[1];
|
||||
ret.elem = elemRet[1]
|
||||
}
|
||||
|
||||
ret.allegiance = title("Allegiance");
|
||||
ret.weapon = title("Weapon Type");
|
||||
ret.britydah = title("Birthday");
|
||||
ret.astro = title("Astrolabe Name");
|
||||
ret.cncv = title("Chinese Seiyuu");
|
||||
ret.jpcv = title("Japanese Seiyuu");
|
||||
ret.desc = title("In-game Description");
|
||||
return ret;
|
||||
ret.allegiance = title('Allegiance')
|
||||
ret.weapon = title('Weapon Type')
|
||||
ret.britydah = title('Birthday')
|
||||
ret.astro = title('Astrolabe Name')
|
||||
ret.cncv = title('Chinese Seiyuu')
|
||||
ret.jpcv = title('Japanese Seiyuu')
|
||||
ret.desc = title('In-game Description')
|
||||
return ret
|
||||
}
|
||||
|
||||
function getStat($) {
|
||||
function getStat ($) {
|
||||
// 采集属性信息
|
||||
let stat = $("#beta_scroll_stat").next(".skilldmgwrapper").find("table");
|
||||
let attrs = [], idx = 4;
|
||||
stat.find("tr:first td:gt(0)").each(function (i) {
|
||||
let title = $(this).text();
|
||||
if (title === "Ascension") {
|
||||
idx = i + 1;
|
||||
console.log(idx);
|
||||
return false;
|
||||
let stat = $('#beta_scroll_stat').next('.skilldmgwrapper').find('table')
|
||||
let attrs = []
|
||||
let idx = 4
|
||||
stat.find('tr:first td:gt(0)').each(function (i) {
|
||||
let title = $(this).text()
|
||||
if (title === 'Ascension') {
|
||||
idx = i + 1
|
||||
console.log(idx)
|
||||
return false
|
||||
}
|
||||
attrs.push($(this).text())
|
||||
})
|
||||
let lvs = [], lvStat = {};
|
||||
stat.find("tr:gt(0)").each(function (i) {
|
||||
let tr = $(this), lvl = tr.find("td:first").text();
|
||||
lvs.push(lvl);
|
||||
let data = [];
|
||||
let lvs = []
|
||||
let lvStat = {}
|
||||
stat.find('tr:gt(0)').each(function (i) {
|
||||
let tr = $(this)
|
||||
let lvl = tr.find('td:first').text()
|
||||
lvs.push(lvl)
|
||||
let data = []
|
||||
tr.find(`td:lt(${idx})`).each(function (i) {
|
||||
if (i > 0) {
|
||||
data.push($(this).text())
|
||||
}
|
||||
})
|
||||
lvStat[lvl] = data;
|
||||
});
|
||||
lvStat[lvl] = data
|
||||
})
|
||||
return {
|
||||
lvs,
|
||||
stat: attrs,
|
||||
detail: lvStat
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function getTalents($, eq, onlyLv1 = false) {
|
||||
let root = $("#beta_scroll_attack_talent");
|
||||
let info = root.nextAll(`.item_main_table:eq(${eq})`);
|
||||
function getTalents ($, eq, onlyLv1 = false) {
|
||||
let root = $('#beta_scroll_attack_talent')
|
||||
let info = root.nextAll(`.item_main_table:eq(${eq})`)
|
||||
|
||||
let name = info.find("tr:first td:eq(1)").text();
|
||||
let icon = info.find("tr:first td:first img").attr("data-src");
|
||||
let name = info.find('tr:first td:eq(1)').text()
|
||||
let icon = info.find('tr:first td:first img').attr('data-src')
|
||||
|
||||
// 说明
|
||||
let desc = info.find("tr:eq(1) td div.skill_desc_layout").html();
|
||||
desc = desc.replace(/<color=[^>]*>/g, "");
|
||||
desc = desc.replace(/<\/color=[^>]*>/g, "");
|
||||
desc = desc.replace(/<span class=[^>]*>/g, "<strong>");
|
||||
desc = desc.replace(/<\/span>/g, "</strong>");
|
||||
desc = desc.split("<br>");
|
||||
let desc = info.find('tr:eq(1) td div.skill_desc_layout').html()
|
||||
desc = desc.replace(/<color=[^>]*>/g, '')
|
||||
desc = desc.replace(/<\/color=[^>]*>/g, '')
|
||||
desc = desc.replace(/<span class=[^>]*>/g, '<strong>')
|
||||
desc = desc.replace(/<\/span>/g, '</strong>')
|
||||
desc = desc.split('<br>')
|
||||
lodash.forEach(desc, (txt, i) => {
|
||||
desc[i] = lodash.trim(txt);
|
||||
desc[i] = lodash.trim(txt)
|
||||
})
|
||||
|
||||
// detail
|
||||
let detail = root.nextAll(`.skilldmgwrapper:eq(${eq})`).find("table");
|
||||
let lvs = [], details = [];
|
||||
detail.find("tr:first td").each(function (i) {
|
||||
let detail = root.nextAll(`.skilldmgwrapper:eq(${eq})`).find('table')
|
||||
let lvs = []
|
||||
let details = []
|
||||
detail.find('tr:first td').each(function (i) {
|
||||
if (onlyLv1 && i > 1) {
|
||||
return false;
|
||||
return false
|
||||
}
|
||||
if (i > 0) {
|
||||
lvs.push($(this).text())
|
||||
}
|
||||
});
|
||||
detail.find("tr:gt(0)").each(function () {
|
||||
let name = $(this).find("td:eq(0)").text();
|
||||
let values = [], isSame = true;
|
||||
$(this).find("td:gt(0)").each(function (i) {
|
||||
})
|
||||
detail.find('tr:gt(0)').each(function () {
|
||||
let name = $(this).find('td:eq(0)').text()
|
||||
let values = []
|
||||
let isSame = true
|
||||
$(this).find('td:gt(0)').each(function (i) {
|
||||
if (onlyLv1 && i > 0) {
|
||||
return false;
|
||||
return false
|
||||
}
|
||||
let val = lodash.trim($(this).text());
|
||||
values.push(val);
|
||||
let val = lodash.trim($(this).text())
|
||||
values.push(val)
|
||||
if (i > 0 && values[0] !== val) {
|
||||
isSame = false;
|
||||
isSame = false
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
details.push({
|
||||
name, isSame, values
|
||||
})
|
||||
});
|
||||
})
|
||||
|
||||
return {
|
||||
name,
|
||||
@ -132,52 +138,50 @@ function getTalents($, eq, onlyLv1 = false) {
|
||||
tables: details,
|
||||
lvs
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
let getPassive = function ($, name) {
|
||||
let table = $("#beta_scroll_passive_talent").next("table")
|
||||
let ret = [];
|
||||
let table = $('#beta_scroll_passive_talent').next('table')
|
||||
let ret = []
|
||||
|
||||
|
||||
table.find("tr").each(function (idx) {
|
||||
table.find('tr').each(function (idx) {
|
||||
if (idx % 2 === 0) {
|
||||
let ds = {};
|
||||
ds.icon = $(this).find("td:first img").attr("data-src");
|
||||
ds.name = $(this).find("td:eq(1)").text();
|
||||
ret[idx / 2] = ds;
|
||||
let ds = {}
|
||||
ds.icon = $(this).find('td:first img').attr('data-src')
|
||||
ds.name = $(this).find('td:eq(1)').text()
|
||||
ret[idx / 2] = ds
|
||||
} else {
|
||||
ret[(idx - 1) / 2].desc = $(this).find("td").text();
|
||||
ret[(idx - 1) / 2].desc = $(this).find('td').text()
|
||||
}
|
||||
})
|
||||
if (name === "莫娜" || name === "神里绫华") {
|
||||
if (name === '莫娜' || name === '神里绫华') {
|
||||
ret.push(getTalents($, 2, true))
|
||||
}
|
||||
return ret;
|
||||
return ret
|
||||
}
|
||||
|
||||
let getCons = function ($) {
|
||||
let table = $("#beta_scroll_constellation").next("table")
|
||||
let ret = {};
|
||||
table.find("tr").each(function (idx) {
|
||||
let table = $('#beta_scroll_constellation').next('table')
|
||||
let ret = {}
|
||||
table.find('tr').each(function (idx) {
|
||||
if (idx % 2 === 0) {
|
||||
let ds = {};
|
||||
ds.icon = $(this).find("td:first img").attr("data-src");
|
||||
ds.name = $(this).find("td:eq(1)").text();
|
||||
ret[idx / 2 + 1] = ds;
|
||||
let ds = {}
|
||||
ds.icon = $(this).find('td:first img').attr('data-src')
|
||||
ds.name = $(this).find('td:eq(1)').text()
|
||||
ret[idx / 2 + 1] = ds
|
||||
} else {
|
||||
ret[(idx + 1) / 2].desc = $(this).find("td").text();
|
||||
ret[(idx + 1) / 2].desc = $(this).find('td').text()
|
||||
}
|
||||
})
|
||||
return ret;
|
||||
return ret
|
||||
}
|
||||
|
||||
let getImgs = function ($) {
|
||||
let cont = $("#scroll_gallery").next(".homepage_index_cont");
|
||||
let cont = $('#scroll_gallery').next('.homepage_index_cont')
|
||||
let img = function (idx, _cont) {
|
||||
return (_cont || cont).find(`.gallery_content_cont:eq(${idx}) a`).attr("href");
|
||||
return (_cont || cont).find(`.gallery_content_cont:eq(${idx}) a`).attr('href')
|
||||
}
|
||||
let card = $("#scroll_name_card").nextAll(".homepage_index_cont:first");
|
||||
let card = $('#scroll_name_card').nextAll('.homepage_index_cont:first')
|
||||
return {
|
||||
face: img(0),
|
||||
side: img(1),
|
||||
@ -185,98 +189,56 @@ let getImgs = function ($) {
|
||||
gacha_splash: img(3),
|
||||
profile: img(1, card),
|
||||
party: img(2, card),
|
||||
char: $("#live_data table.item_main_table:first td:first img").attr("data-src")
|
||||
char: $('#live_data table.item_main_table:first td:first img').attr('data-src')
|
||||
}
|
||||
}
|
||||
|
||||
let getCharData = async function (url, key, name = '') {
|
||||
let getCharData = async function (url, name = '') {
|
||||
url = 'https://genshin.honeyhunterworld.com/' + url
|
||||
console.log('req' + url)
|
||||
|
||||
url = "https://genshin.honeyhunterworld.com/" + url;
|
||||
console.log('req' + key, url)
|
||||
let req = await fetch(url)
|
||||
let txt = await req.text()
|
||||
|
||||
let req = await fetch(url);
|
||||
let txt = await req.text();
|
||||
const $ = cheerio.load(txt)
|
||||
let ret = getBasic($, name)
|
||||
name = ret.name
|
||||
|
||||
const $ = cheerio.load(txt);
|
||||
let ret = getBasic($, name);
|
||||
|
||||
name = ret.name;
|
||||
|
||||
ret.lvStat = getStat($);
|
||||
ret.lvStat = getStat($)
|
||||
ret.talent = {
|
||||
a: getTalents($, 0),
|
||||
e: getTalents($, 1),
|
||||
q: getTalents($, name === "莫娜" || name === "神里绫华" ? 3 : 2)
|
||||
q: getTalents($, name === '莫娜' || name === '神里绫华' ? 3 : 2)
|
||||
}
|
||||
ret.passive = getPassive($, name);
|
||||
ret.cons = getCons($);
|
||||
ret.imgs = getImgs($);
|
||||
return ret;
|
||||
ret.passive = getPassive($, name)
|
||||
ret.cons = getCons($)
|
||||
ret.imgs = getImgs($)
|
||||
return ret
|
||||
}
|
||||
|
||||
async function saveCharData(url, key, name) {
|
||||
async function saveCharData (url, name) {
|
||||
let data = await getCharData(url, name)
|
||||
|
||||
let data = await getCharData(url, key, name);
|
||||
|
||||
name = name || data.name;
|
||||
name = name || data.name
|
||||
|
||||
if (!name) {
|
||||
console.log("角色名不存在" + url);
|
||||
return;
|
||||
console.log('角色名不存在' + url)
|
||||
return
|
||||
}
|
||||
|
||||
let charPath = `${_path}/plugins/miao-plugin/resources/meta/character/${data.name}/`
|
||||
if (!fs.existsSync(charPath)) {
|
||||
fs.mkdirSync(charPath);
|
||||
fs.mkdirSync(charPath)
|
||||
}
|
||||
|
||||
fs.writeFileSync(`${charPath}data.json`, JSON.stringify(data, "", "\t"));
|
||||
console.log(data.name + "下载完成");
|
||||
fs.writeFileSync(`${charPath}data.json`, JSON.stringify(data, '', '\t'))
|
||||
console.log(data.name + '下载完成')
|
||||
}
|
||||
|
||||
async function down() {
|
||||
//const url = "https://genshin.honeyhunterworld.com/db/char/characters/?lang=CHS";
|
||||
const url = "https://genshin.honeyhunterworld.com/db/char/unreleased-and-upcoming-characters/?lang=CHS";
|
||||
let req = await fetch(url);
|
||||
let txt = await req.text();
|
||||
let $ = cheerio.load(txt);
|
||||
let char = $(".char_sea_cont");
|
||||
|
||||
char.each(async function () {
|
||||
let url = $(this).find("a:first").attr("href");
|
||||
let keyRet = /\/char\/(\w*)\//.exec(url);
|
||||
|
||||
|
||||
if (keyRet && keyRet[1]) {
|
||||
let key = keyRet[1],
|
||||
tRet = /traveler_(girl|boy)_(\w*)/.exec(key),
|
||||
name;
|
||||
|
||||
if (tRet) {
|
||||
if (tRet[1] === "girl") {
|
||||
name = { anemo: "风", geo: "岩", electro: "雷" }[tRet[2]] + "主";
|
||||
} else {
|
||||
return
|
||||
}
|
||||
}
|
||||
let nameMap = { dori: "多莉", tighnari: "提纳里", collei: "柯莱" }
|
||||
if (nameMap[key]) {
|
||||
name = nameMap[key];
|
||||
}
|
||||
|
||||
|
||||
await saveCharData(url, key, name);
|
||||
}
|
||||
});
|
||||
|
||||
async function down () {
|
||||
await saveCharData('/collei_067/?lang=CHS', '柯莱')
|
||||
}
|
||||
|
||||
//await saveCharData("https://genshin.honeyhunterworld.com/db/char/ayaka/?lang=CHS", "ayaka");
|
||||
|
||||
|
||||
await down();
|
||||
|
||||
|
||||
|
||||
|
||||
// await saveCharData("https://genshin.honeyhunterworld.com/db/char/ayaka/?lang=CHS", "ayaka");
|
||||
|
||||
await down()
|
||||
|
Loading…
Reference in New Issue
Block a user