diff --git a/adapter/index.js b/adapter/index.js index 8b47684f..66151c46 100644 --- a/adapter/index.js +++ b/adapter/index.js @@ -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 } diff --git a/adapter/lib/plugin.js b/adapter/lib/plugin.js new file mode 100644 index 00000000..7dec3776 --- /dev/null +++ b/adapter/lib/plugin.js @@ -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] + } + } +} diff --git a/adapter/lib/puppeteer.js b/adapter/lib/puppeteer.js new file mode 100644 index 00000000..2592fde1 --- /dev/null +++ b/adapter/lib/puppeteer.js @@ -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() diff --git a/adapter/mys.js b/adapter/mys.js index 226ee63c..bb2897e8 100644 --- a/adapter/mys.js +++ b/adapter/mys.js @@ -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) { diff --git a/adapter/render.js b/adapter/render.js deleted file mode 100644 index 1cfb3c6f..00000000 --- a/adapter/render.js +++ /dev/null @@ -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) -} diff --git a/adapter/v3-entrance.js b/adapter/v3-entrance.js new file mode 100644 index 00000000..ab04c1fb --- /dev/null +++ b/adapter/v3-entrance.js @@ -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 + } +} diff --git a/apps/admin.js b/apps/admin.js index dfaca75d..33b0cd28 100644 --- a/apps/admin.js +++ b/apps/admin.js @@ -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 }) } diff --git a/apps/character.js b/apps/character.js index 6f0e1255..2a04761a 100644 --- a/apps/character.js +++ b/apps/character.js @@ -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 } diff --git a/apps/character/avatar-card.js b/apps/character/avatar-card.js index fc9abb02..74f1b111 100644 --- a/apps/character/avatar-card.js +++ b/apps/character/avatar-card.js @@ -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 }) diff --git a/apps/character/avatar-wife.js b/apps/character/avatar-wife.js index ca0e03a7..38d2710e 100644 --- a/apps/character/avatar-wife.js +++ b/apps/character/avatar-wife.js @@ -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('在当前米游社公开展示的角色中未能找到适合展示的角色..') diff --git a/apps/character/character-img-upload.js b/apps/character/character-img-upload.js index 526a942d..7297d343 100644 --- a/apps/character/character-img-upload.js +++ b/apps/character/character-img-upload.js @@ -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 diff --git a/apps/character/profile-artis.js b/apps/character/profile-artis.js index cc4d2284..4031fe01 100644 --- a/apps/character/profile-artis.js +++ b/apps/character/profile-artis.js @@ -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 }) } diff --git a/apps/character/profile-common.js b/apps/character/profile-common.js index 54a2cee6..3843d342 100644 --- a/apps/character/profile-common.js +++ b/apps/character/profile-common.js @@ -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 diff --git a/apps/character/profile-detail.js b/apps/character/profile-detail.js index 9b46b942..6cac5740 100644 --- a/apps/character/profile-detail.js +++ b/apps/character/profile-detail.js @@ -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 }) } diff --git a/apps/character/profile-list.js b/apps/character/profile-list.js index 006dc327..00148884 100644 --- a/apps/character/profile-list.js +++ b/apps/character/profile-list.js @@ -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 }) } diff --git a/apps/character/profile-stat.js b/apps/character/profile-stat.js index efa40050..72c4b094 100644 --- a/apps/character/profile-stat.js +++ b/apps/character/profile-stat.js @@ -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 }) } diff --git a/apps/help.js b/apps/help.js index c1f87823..9cedcb0f 100644 --- a/apps/help.js +++ b/apps/help.js @@ -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 }) } diff --git a/apps/stat.js b/apps/stat.js index 15c4a67e..ba69cc74 100644 --- a/apps/stat.js +++ b/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 diff --git a/apps/wiki.js b/apps/wiki.js index 0b8d00ee..6f1386d6 100644 --- a/apps/wiki.js +++ b/apps/wiki.js @@ -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 }) } diff --git a/components/Common.js b/components/Common.js index ae3fe5c0..8e1bab63 100644 --- a/components/Common.js +++ b/components/Common.js @@ -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${Version.yunzai} & Miao-Plugin${Version.version}` } - }) - + } + 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 } diff --git a/config/system/character.js b/config/system/character.js index 7b7ecef0..6553d668 100644 --- a/config/system/character.js +++ b/config/system/character.js @@ -75,7 +75,7 @@ export const characters = { // 以下为Miao新增自定义角色 paimon: ['派蒙', '应急食物', '应急食品', '吉祥物', '宠物', '外置器官', '会说话的动物', '矮堇瓜', '飞行矮堇瓜', '最好的伙伴'], - sb: ['散兵', '国崩', '雷电国崩', '大炮', '雷电大炮', '雷大炮', '伞兵', '斯卡拉姆齐'], + sanbing: ['散兵', '国崩', '雷电国崩', '大炮', '雷电大炮', '雷大炮', '伞兵', '斯卡拉姆齐'], nvshi: ['女士', '炽热的炎之魔女', '炎之魔女', '罗莎琳'], baizhu: ['白术', '长生'], yaoyao: ['瑶瑶', '遥遥', '遥遥无期'], diff --git a/index.js b/index.js index af42bf53..5474324f 100644 --- a/index.js +++ b/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}初始化~`) diff --git a/models/Artifact.js b/models/Artifact.js index 90b888fa..e2514ec2 100644 --- a/models/Artifact.js +++ b/models/Artifact.js @@ -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' diff --git a/models/ProfileArtis.js b/models/ProfileArtis.js index 950d055b..bf1495a8 100644 --- a/models/ProfileArtis.js +++ b/models/ProfileArtis.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 = {} diff --git a/models/profile-lib/ArtisMark.js b/models/profile-lib/ArtisMark.js index 951605f0..ea081e33 100644 --- a/models/profile-lib/ArtisMark.js +++ b/models/profile-lib/ArtisMark.js @@ -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) { diff --git a/models/profile-lib/Calc.js b/models/profile-lib/Calc.js deleted file mode 100644 index 12e833d0..00000000 --- a/models/profile-lib/Calc.js +++ /dev/null @@ -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 diff --git a/models/profile-lib/DmgAttr.js b/models/profile-lib/DmgAttr.js index cdd7f288..d0120335 100644 --- a/models/profile-lib/DmgAttr.js +++ b/models/profile-lib/DmgAttr.js @@ -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) }) } diff --git a/models/profile-lib/DmgCalc.js b/models/profile-lib/DmgCalc.js index 7ba2e843..baf1233d 100644 --- a/models/profile-lib/DmgCalc.js +++ b/models/profile-lib/DmgCalc.js @@ -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) diff --git a/models/profile-lib/Mastery.js b/models/profile-lib/DmgMastery.js similarity index 88% rename from models/profile-lib/Mastery.js rename to models/profile-lib/DmgMastery.js index 573069fd..d1273901 100644 --- a/models/profile-lib/Mastery.js +++ b/models/profile-lib/DmgMastery.js @@ -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 diff --git a/resources/admin/index.css b/resources/admin/index.css index fa5eb0a2..c72dbd9b 100644 --- a/resources/admin/index.css +++ b/resources/admin/index.css @@ -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 */ \ No newline at end of file +/*# sourceMappingURL=index.css.map */ \ No newline at end of file diff --git a/resources/admin/index.less b/resources/admin/index.less index 2df4b93b..0d0fe814 100644 --- a/resources/admin/index.less +++ b/resources/admin/index.less @@ -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 { diff --git a/resources/character/artis.css b/resources/character/artis-list.css similarity index 92% rename from resources/character/artis.css rename to resources/character/artis-list.css index 9c3d3e59..3f80f607 100644 --- a/resources/character/artis.css +++ b/resources/character/artis-list.css @@ -32,4 +32,4 @@ max-width: 100%; max-height: 100%; } -/*# sourceMappingURL=artis.css.map */ \ No newline at end of file +/*# sourceMappingURL=artis-list.css.map */ \ No newline at end of file diff --git a/resources/character/artis.html b/resources/character/artis-list.html similarity index 97% rename from resources/character/artis.html rename to resources/character/artis-list.html index 62d0bef3..0fdcb94b 100644 --- a/resources/character/artis.html +++ b/resources/character/artis-list.html @@ -2,7 +2,7 @@ {{block 'css'}} - + {{/block}} {{block 'main'}} diff --git a/resources/character/artis.less b/resources/character/artis-list.less similarity index 100% rename from resources/character/artis.less rename to resources/character/artis-list.less diff --git a/resources/character/card.css b/resources/character/character-card.css similarity index 99% rename from resources/character/card.css rename to resources/character/character-card.css index 705933a9..fb55fbb3 100644 --- a/resources/character/card.css +++ b/resources/character/character-card.css @@ -434,4 +434,4 @@ body.bottom_mode { .bottom_mode .no-info { bottom: 25px; } -/*# sourceMappingURL=card.css.map */ \ No newline at end of file +/*# sourceMappingURL=character-card.css.map */ \ No newline at end of file diff --git a/resources/character/card.html b/resources/character/character-card.html similarity index 98% rename from resources/character/card.html rename to resources/character/character-card.html index fcc53555..1ad1a44d 100644 --- a/resources/character/card.html +++ b/resources/character/character-card.html @@ -4,7 +4,7 @@ - + diff --git a/resources/character/card.less b/resources/character/character-card.less similarity index 99% rename from resources/character/card.less rename to resources/character/character-card.less index 386681a9..c5da7847 100644 --- a/resources/character/card.less +++ b/resources/character/character-card.less @@ -487,7 +487,6 @@ body.bottom_mode { .copyright { position: absolute; - //font-family: Number, YS; margin-bottom: 0; } diff --git a/resources/common/tpl.css b/resources/common/tpl.css index a56ba3a2..edb8a603 100644 --- a/resources/common/tpl.css +++ b/resources/common/tpl.css @@ -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; } diff --git a/resources/common/tpl/artis-detail.less b/resources/common/tpl/artis-detail.less index 19c0d11e..577e0700 100644 --- a/resources/common/tpl/artis-detail.less +++ b/resources/common/tpl/artis-detail.less @@ -95,7 +95,6 @@ &.val { text-align: right; padding-right: 10px; - //font-family: Number; } } diff --git a/resources/help/index.less b/resources/help/index.less index e9e4b88e..9f06a2a2 100644 --- a/resources/help/index.less +++ b/resources/help/index.less @@ -11,7 +11,6 @@ body { } .label { - //font-family: Number, "微软雅黑", sans-serif; } .head-box { diff --git a/resources/meta/character/芭芭拉/calc.js b/resources/meta/character/芭芭拉/calc.js index f9e00ef7..fa3e2b71 100644 --- a/resources/meta/character/芭芭拉/calc.js +++ b/resources/meta/character/芭芭拉/calc.js @@ -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 +} diff --git a/resources/meta/reliquaries/reliquaries-mark-new.js b/resources/meta/reliquaries/artis-mark.js similarity index 100% rename from resources/meta/reliquaries/reliquaries-mark-new.js rename to resources/meta/reliquaries/artis-mark.js diff --git a/resources/meta/reliquaries/reliquaries-mark.js b/resources/meta/reliquaries/reliquaries-mark.js deleted file mode 100644 index dfa6389d..00000000 --- a/resources/meta/reliquaries/reliquaries-mark.js +++ /dev/null @@ -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' -} diff --git a/resources/stat/abyss-team.less b/resources/stat/abyss-team.less index 58251698..2738da93 100644 --- a/resources/stat/abyss-team.less +++ b/resources/stat/abyss-team.less @@ -91,7 +91,6 @@ border-radius: 3px; padding: 1px 5px; background: rgb(0 0 0 / 50%); - //font-family: Number; } .card-list .card .name, diff --git a/resources/stat/common.less b/resources/stat/common.less index 2a53bbad..922ab2ea 100644 --- a/resources/stat/common.less +++ b/resources/stat/common.less @@ -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 { diff --git a/tools/char-data-sprider.js b/tools/char-data-sprider.js index dc5db7d9..0e51d65a 100644 --- a/tools/char-data-sprider.js +++ b/tools/char-data-sprider.js @@ -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(/]*>/g, ""); - desc = desc.replace(/<\/color=[^>]*>/g, ""); - desc = desc.replace(/]*>/g, ""); - desc = desc.replace(/<\/span>/g, ""); - desc = desc.split("
"); + let desc = info.find('tr:eq(1) td div.skill_desc_layout').html() + desc = desc.replace(/]*>/g, '') + desc = desc.replace(/<\/color=[^>]*>/g, '') + desc = desc.replace(/]*>/g, '') + desc = desc.replace(/<\/span>/g, '') + desc = desc.split('
') 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()