mirror of
https://github.com/ZZZure/ZZZ-Plugin.git
synced 2025-12-17 13:47:44 +00:00
548 lines
22 KiB
JavaScript
548 lines
22 KiB
JavaScript
import { ZZZPlugin } from '../lib/plugin.js';
|
||
import {
|
||
getPanelList,
|
||
refreshPanel as refreshPanelFunction,
|
||
getPanelOrigin,
|
||
updatePanelData,
|
||
formatPanelData,
|
||
getPanelListOrigin,
|
||
} from '../lib/avatar.js';
|
||
import settings from '../lib/settings.js';
|
||
import _ from 'lodash';
|
||
import { rulePrefix } from '../lib/common.js';
|
||
import { getZzzEnkaData } from '../lib/ekapi/query.js'
|
||
import { _enka_data_to_mys_data } from '../lib/ekapi/enka_to_mys.js'
|
||
|
||
export class Panel extends ZZZPlugin {
|
||
constructor() {
|
||
super({
|
||
name: '[ZZZ-Plugin]Panel',
|
||
dsc: 'zzzpanel',
|
||
event: 'message',
|
||
priority: _.get(settings.getConfig('priority'), 'panel', 70),
|
||
rule: [
|
||
{
|
||
reg: `${rulePrefix}(.*)面板(刷新|更新|列表)?$`,
|
||
fnc: 'handleRule',
|
||
},
|
||
{
|
||
reg: `${rulePrefix}练度(统计)?$`,
|
||
fnc: 'proficiency',
|
||
},
|
||
{
|
||
reg: `${rulePrefix}原图$`,
|
||
fnc: 'getCharOriImage',
|
||
},
|
||
],
|
||
handler: [
|
||
{ key: 'zzz.tool.panel', fn: 'getCharPanelTool' },
|
||
{ key: 'zzz.tool.panelList', fn: 'getCharPanelListTool' },
|
||
],
|
||
});
|
||
}
|
||
async handleRule() {
|
||
if (!this.e.msg) return;
|
||
const reg = new RegExp(`${rulePrefix}(.*)面板(刷新|更新|列表)?$`);
|
||
const pre = this.e.msg.match(reg)[4]?.trim();
|
||
const suf = this.e.msg.match(reg)[5]?.trim();
|
||
if (['刷新', '更新'].includes(pre) || ['刷新', '更新'].includes(suf))
|
||
return await this.refreshPanel();
|
||
if (!pre || suf === '列表') return await this.getCharPanelList();
|
||
const queryPanelReg = new RegExp(`${rulePrefix}(.*)面板$`);
|
||
if (queryPanelReg.test(this.e.msg)) return await this.getCharPanel();
|
||
return false;
|
||
}
|
||
// async refreshPanel() {
|
||
// const uid = await this.getUID();
|
||
// // ... 省略获取 lastQueryTime 和冷卻时间判断的代码 ...
|
||
// this.result = null; // 先清空结果
|
||
//
|
||
// const useEnka = _.get(settings.getConfig('config'), 'useEnka', false);
|
||
// logger.mark(`[panel.js] useEnka 设置值: ${useEnka}`); // 1. 确认是否启用 Enka 逻辑
|
||
//
|
||
// if (useEnka) { // 检查这个 if 是否进入
|
||
// logger.mark('[panel.js] 进入 useEnka 逻辑块');
|
||
// let enkaData = null; // 初始化 enkaData
|
||
// try {
|
||
// logger.mark(`[panel.js] 准备调用 getZzzEnkaData for UID: ${uid}`);
|
||
// enkaData = await getZzzEnkaData(uid);
|
||
// logger.mark('[panel.js] getZzzEnkaData 调用完成');
|
||
//
|
||
// // 2. 详细检查 enkaData 的状态
|
||
// if (enkaData === null || enkaData === undefined) {
|
||
// logger.error('[panel.js] getZzzEnkaData 返回了 null 或 undefined');
|
||
// await this.reply('获取Enka数据失败 (返回null/undefined),请稍后再试');
|
||
// return false;
|
||
// } else if (enkaData === -1) {
|
||
// logger.warn('[panel.js] getZzzEnkaData 返回了 -1 (表示获取失败)');
|
||
// await this.reply('获取Enka数据失败 (返回-1),请稍后再试');
|
||
// return false;
|
||
// } else if (!enkaData.PlayerInfo || !enkaData.PlayerInfo.ShowcaseDetail || !enkaData.PlayerInfo.ShowcaseDetail.AvatarList) {
|
||
// logger.error('[panel.js] 获取到的 enkaData 结构不完整:', enkaData);
|
||
// await this.reply('获取到的Enka数据结构不完整,无法处理');
|
||
// return false;
|
||
// } else {
|
||
// logger.mark('[panel.js] 成功获取到有效的 enkaData 结构');
|
||
// console.log('[panel.js] enkaData.PlayerInfo.ShowcaseDetail.AvatarList:', enkaData.PlayerInfo.ShowcaseDetail.AvatarList); // 打印角色列表确认
|
||
// }
|
||
//
|
||
// // 3. 检查 _enka_data_to_mys_data 函数是否已正确导入
|
||
// if (typeof _enka_data_to_mys_data !== 'function') {
|
||
// logger.error('[panel.js] _enka_data_to_mys_data 不是一个函数! 请检查导入语句和文件是否存在。');
|
||
// await this.reply('内部错误:数据转换函数加载失败');
|
||
// return false;
|
||
// }
|
||
//
|
||
// logger.mark('[panel.js] _enka_data_to_mys_data 函数已找到,类型:', typeof _enka_data_to_mys_data);
|
||
// logger.mark('[panel.js] 即将调用 _enka_data_to_mys_data...');
|
||
//
|
||
// // 4. 使用 try...catch 包裹调用,捕获可能的内部错误
|
||
// try {
|
||
// this.result = await _enka_data_to_mys_data(enkaData);
|
||
// logger.mark('[panel.js] _enka_data_to_mys_data 调用完成。');
|
||
// // 在这里可以检查 this.result 是否是你期望的格式
|
||
// console.log('[panel.js] 转换后的 result (部分示例):', this.result ? JSON.stringify(this.result[0], null, 2).substring(0, 500) + '...' : 'null or empty');
|
||
// } catch (conversionError) {
|
||
// logger.error('[panel.js] 调用 _enka_data_to_mys_data 时发生严重错误:', conversionError);
|
||
// // 打印详细错误堆栈
|
||
// console.error(conversionError);
|
||
// await this.reply(`处理Enka数据时出错: ${conversionError.message}`);
|
||
// return false; // 出错则不再继续
|
||
// }
|
||
//
|
||
// } catch (fetchError) {
|
||
// // 这个 catch 捕获 getZzzEnkaData 自身的 await 可能抛出的错误
|
||
// logger.error('[panel.js] 调用 getZzzEnkaData 时发生错误:', fetchError);
|
||
// console.error(fetchError); // 打印错误堆栈
|
||
// await this.reply(`获取Enka数据时发生网络或API错误: ${fetchError.message}`);
|
||
// return false;
|
||
// }
|
||
//
|
||
// } else { // 如果 useEnka 是 false
|
||
// logger.mark('[panel.js] 未启用 useEnka,跳过 Enka 面板逻辑');
|
||
// // 这里可以继续执行原有的 mysapi 逻辑(如果需要的话)
|
||
// // logger.mark('mysapi执行');
|
||
// // ... (原有的 mysapi 刷新逻辑) ...
|
||
// // 注意:如果 useEnka 为 false,this.result 可能需要从 mysapi 获取
|
||
// }
|
||
//
|
||
// // ----- 后续处理 this.result 的代码 -----
|
||
// // (确保无论走 Enka 逻辑还是 mysapi 逻辑,this.result 都有合适的值)
|
||
//
|
||
// // 例如,原有的 newChar 计算和渲染逻辑:
|
||
// if (this.result && Array.isArray(this.result)) { // 检查 this.result 是否有效
|
||
// const newChar = this.result.filter(item => item.isNew); // 假设 MYS 数据结构中有 isNew
|
||
// const finalData = {
|
||
// newChar: newChar.length,
|
||
// list: this.result, // 使用转换后的或 mysapi 的结果
|
||
// };
|
||
// await this.render('panel/refresh.html', finalData);
|
||
// } else if (!useEnka) {
|
||
// // 如果没用 Enka 且没有执行 mysapi 逻辑(或 mysapi 逻辑没产生 result),可能需要提示
|
||
// logger.warn('[panel.js] 没有可用的面板数据用于渲染 (useEnka=false, result无效)');
|
||
// // 可能需要添加回复告诉用户没有数据?
|
||
// } else if (useEnka && (!this.result || this.result.length === 0)) {
|
||
// logger.warn('[panel.js] Enka 数据转换后结果为空或无效');
|
||
// // 根据需要决定是否回复用户
|
||
// }
|
||
//
|
||
// }
|
||
|
||
// async refreshPanel() {
|
||
// const uid = await this.getUID();
|
||
// const lastQueryTime = await redis.get(`ZZZ:PANEL:${uid}:LASTTIME`);
|
||
// const panelSettings = settings.getConfig('panel');
|
||
// const coldTime = _.get(panelSettings, 'interval', 300);
|
||
// this.result = null; // Initialize instance result
|
||
//
|
||
// // --- Enka Path ---
|
||
// if(_.get(settings.getConfig('config'), 'useEnka', false)){ // Default is false if setting missing
|
||
// logger.mark('enka面板执行')
|
||
// const enkaData = await getZzzEnkaData(uid); // Fetch Enka data
|
||
//
|
||
// // --- Issue 1: Check for failure *before* processing ---
|
||
// if (enkaData === -1) { // Check for specific failure code
|
||
// await this.reply('获取enka数据失败,请稍后再试');
|
||
// return false; // Exit early
|
||
// }
|
||
// // Add more checks for null/undefined/incomplete data if needed here
|
||
//
|
||
// console.log('[panel.js] 获取到 enkaData,准备转换...');
|
||
// console.log('Enka AvatarList:', enkaData?.PlayerInfo?.ShowcaseDetail?.AvatarList);
|
||
// console.log('[panel.js] 即将调用 _enka_data_to_mys_data...');
|
||
//
|
||
// // --- This is where previous errors occurred due to name_convert.js load failure ---
|
||
// // Assuming name_convert.js path fix is applied, this should now work
|
||
// this.result = await _enka_data_to_mys_data(enkaData); // Assign to instance variable
|
||
// logger.mark('[panel.js] _enka_data_to_mys_data 调用完成.'); // Added log for confirmation
|
||
//
|
||
// // --- MYS API Path ---
|
||
// } else {
|
||
// logger.mark('mysapi执行')
|
||
// if (lastQueryTime && Date.now() - lastQueryTime < 1000 * coldTime) {
|
||
// await this.reply(`${coldTime}秒内只能刷新一次,请稍后再试`);
|
||
// return false;
|
||
// }
|
||
// const { api } = await this.getAPI();
|
||
// await redis.set(`ZZZ:PANEL:${uid}:LASTTIME`, Date.now());
|
||
// await this.reply('正在刷新面板列表,请稍候...');
|
||
// await this.getPlayerInfo(); // Assumed necessary for MYS panel
|
||
//
|
||
// // --- Issue 2: Assign result correctly ---
|
||
// let mysResult = null; // Use a temporary variable for MYS result
|
||
// try {
|
||
// mysResult = await refreshPanelFunction(api); // Call the imported MYS refresh
|
||
// console.dir('MYS API res:', mysResult); // Log MYS result
|
||
// if (!mysResult) {
|
||
// await this.reply('面板列表刷新失败 (MYS API),请稍后再试');
|
||
// return false;
|
||
// }
|
||
// // Assign the successful MYS result to the instance variable
|
||
// this.result = mysResult; // <<<< IMPORTANT ASSIGNMENT
|
||
// } catch (e) {
|
||
// this.reply(e.message);
|
||
// // Consider logging the full error for debugging
|
||
// logger.error("MYS API refresh failed:", e);
|
||
// // Depending on desired behavior, you might return false or re-throw
|
||
// return false; // Exit on MYS API error
|
||
// }
|
||
// } // End if/else
|
||
//
|
||
// // --- Post-processing: Use this.result consistently ---
|
||
// // Ensure this.result is an array before proceeding
|
||
// if (!this.result || !Array.isArray(this.result)) {
|
||
// logger.error('[panel.js] 最终结果无效或不是数组:', this.result);
|
||
// // Maybe reply to the user that no data could be processed
|
||
// await this.reply('未能获取或处理有效的面板数据。');
|
||
// return false;
|
||
// }
|
||
//
|
||
// // --- Issue 3: Use this.result for calculations ---
|
||
// // Filter based on the unified this.result
|
||
// const newChar = this.result.filter(item => item && item.isNew); // Added check for item existence
|
||
//
|
||
// // Prepare final data using the unified this.result
|
||
// const finalData = {
|
||
// newChar: newChar.length,
|
||
// list: this.result, // Use the instance variable
|
||
// };
|
||
//
|
||
// // Render the result
|
||
// await this.render('panel/refresh.html', finalData);
|
||
// }
|
||
async refreshPanel() {
|
||
const uid = await this.getUID();
|
||
// --- 获取玩家信息 (带容错处理) ---
|
||
// ... (这部分代码保持不变,使用带有占位符逻辑的版本) ...
|
||
logger.mark('[panel.js] 准备调用 getPlayerInfo...');
|
||
let playerInfo = null;
|
||
try {
|
||
playerInfo = await this.getPlayerInfo();
|
||
if (!playerInfo) playerInfo = this.e.player;
|
||
if (!playerInfo) {
|
||
logger.warn(`[panel.js] getPlayerInfo 未返回有效信息,使用默认占位。UID: ${uid}`);
|
||
playerInfo = { uid: uid, nickname: `用户${uid}`, level: '??', region_name: '未知服务器' };
|
||
}
|
||
logger.mark('[panel.js] getPlayerInfo 尝试完成.');
|
||
} catch (playerInfoError) {
|
||
logger.error('[panel.js] 调用 getPlayerInfo 时出错 (使用占位):', playerInfoError.message);
|
||
playerInfo = { uid: uid, nickname: `用户${uid}`, level: '??', region_name: '错误', error: playerInfoError.message };
|
||
}
|
||
// --- End 获取玩家信息 ---
|
||
|
||
this.result = null; // 初始化结果
|
||
|
||
// ----- 选择 Enka 或 MYS API -----
|
||
const useEnka = _.get(settings.getConfig('config'), 'useEnka', true); // 读取配置,Enka 优先
|
||
logger.mark(`[panel.js] useEnka 设置值: ${useEnka}`);
|
||
// ----- End -----
|
||
|
||
// --- 数据获取和处理逻辑 ---
|
||
if (useEnka) {
|
||
logger.mark('[panel.js] 进入 Enka 逻辑块');
|
||
try {
|
||
const enkaData = await getZzzEnkaData(uid);
|
||
|
||
logger.mark('[panel.js] getZzzEnkaData 调用完成.'); // <-- 日志:调用后
|
||
|
||
// ----- !!! 在这里添加打印原始 Enka 数据的日志 !!! -----
|
||
console.log('===== ZZZ Enka Raw Data Start =====');
|
||
// 使用 JSON.stringify 完整打印,null, 2 用于格式化输出
|
||
console.log(JSON.stringify(enkaData, null, 2));
|
||
console.log('===== ZZZ Enka Raw Data End =====');
|
||
// ----- !!! 日志添加结束 !!! -----
|
||
|
||
if (!enkaData || enkaData === -1 || !enkaData.PlayerInfo) { throw new Error('获取或验证 Enka 数据失败'); }
|
||
logger.mark('[panel.js] 即将调用 _enka_data_to_mys_data...');
|
||
this.result = await _enka_data_to_mys_data(enkaData); // <<< Enka 结果赋给 this.result
|
||
logger.mark('[panel.js] _enka_data_to_mys_data 调用完成.');
|
||
|
||
// ----- !!! 在这里添加打印转换后数据的日志 !!! -----
|
||
console.log('===== Enka Converted Data (First Avatar) Start =====');
|
||
if (this.result && Array.isArray(this.result) && this.result.length > 0) {
|
||
console.log(JSON.stringify(this.result[0], null, 2)); // 打印第一个转换后的角色
|
||
} else {
|
||
console.log('Converted result is empty or invalid.');
|
||
}
|
||
console.log('===== Enka Converted Data (First Avatar) End =====');
|
||
// ----- !!! 日志添加结束 !!! -----
|
||
logger.mark('[panel.js] _enka_data_to_mys_data 调用完成.');
|
||
} catch (enkaError) {
|
||
logger.error('[panel.js] 处理 Enka 逻辑时出错:', enkaError);
|
||
await this.reply(`处理Enka数据时出错: ${enkaError.message}`);
|
||
return false;
|
||
}
|
||
} else {
|
||
logger.mark('[panel.js] 进入 mysapi 逻辑块');
|
||
try {
|
||
const { api } = await this.getAPI(); // MYS 需要 api 对象
|
||
// MYS 逻辑需要冷却判断
|
||
const lastQueryTime = await redis.get(`ZZZ:PANEL:${uid}:LASTTIME`);
|
||
const panelSettings = settings.getConfig('panel');
|
||
const coldTime = _.get(panelSettings, 'interval', 300);
|
||
if (lastQueryTime && Date.now() - lastQueryTime < 1000 * coldTime) {
|
||
await this.reply(`${coldTime}秒内只能刷新一次,请稍后再试`);
|
||
return false;
|
||
}
|
||
await redis.set(`ZZZ:PANEL:${uid}:LASTTIME`, Date.now());
|
||
await this.reply('正在刷新面板列表 (MYS API),请稍候...');
|
||
|
||
const mysResult = await refreshPanelFunction(api); // 调用 MYS 刷新函数
|
||
if (!mysResult) { throw new Error('MYS API 返回空结果'); }
|
||
this.result = mysResult; // <<< MYS 结果赋给 this.result
|
||
logger.mark('[panel.js] MYS API refreshPanelFunction 调用完成.');
|
||
} catch (mysError) {
|
||
logger.error('[panel.js] MYS API 刷新出错:', mysError);
|
||
this.reply(`MYS API 刷新出错: ${mysError.message}`);
|
||
return false;
|
||
}
|
||
}
|
||
// --- End 数据获取和处理逻辑 ---
|
||
|
||
|
||
// --- !!! 关键步骤:更新面板数据缓存 !!! ---
|
||
if (this.result && Array.isArray(this.result)) { // 确保有有效数据 (非 null, 是数组)
|
||
// 并且至少包含一个角色数据才存,避免存空数组?(可选)
|
||
if (this.result.length > 0) {
|
||
try {
|
||
logger.mark(`[panel.js] 准备调用 updatePanelData 更新缓存,包含 ${this.result.length} 个角色数据...`);
|
||
// 调用导入的 updatePanelData 函数
|
||
await updatePanelData(uid, this.result); // <<< 核心:写入缓存
|
||
logger.mark('[panel.js] updatePanelData 调用完成,缓存已更新。');
|
||
} catch (cacheError) {
|
||
logger.error('[panel.js] 调用 updatePanelData 更新缓存时出错:', cacheError);
|
||
// 记录错误,但可能继续
|
||
}
|
||
} else {
|
||
logger.warn('[panel.js] 获取到的角色列表为空数组,不执行缓存更新。');
|
||
// 如果是 Enka 路径且展示柜为空,这是正常情况
|
||
}
|
||
} else {
|
||
logger.warn('[panel.js] 没有有效的角色列表数据 (this.result),跳过缓存更新。');
|
||
// 如果之前的步骤没有 return false,这里可能需要提示用户
|
||
if (!useEnka) { // MYS 失败的情况
|
||
await this.reply('未能获取或处理有效的面板列表数据。');
|
||
return false; // 如果 MYS 失败且结果无效,应该退出
|
||
}
|
||
// 如果是 Enka 路径且结果无效/非数组,也提示并退出
|
||
await this.reply('处理后的面板数据格式无效。');
|
||
return false;
|
||
}
|
||
// --- !!! End 更新缓存 !!! ---
|
||
|
||
|
||
// --- 后续处理:构建 finalData 用于渲染刷新摘要 ---
|
||
const currentResult = this.result || []; // 保证 currentResult 是数组
|
||
|
||
// newChar 的计算可能依赖于 MYS 的特定字段,Enka 结果可能没有
|
||
// 保持之前的兼容逻辑,如果 Enka 结果没有 isNew,newCharCount 为 0
|
||
const newCharCount = (currentResult.length > 0 && currentResult[0]?.isNew !== undefined)
|
||
? currentResult.filter(item => item && item.isNew).length
|
||
: 0;
|
||
|
||
const finalData = {
|
||
newChar: newCharCount,
|
||
list: currentResult,
|
||
player: playerInfo,
|
||
uid: uid
|
||
};
|
||
|
||
logger.mark('[panel.js] 准备渲染 refresh.html 模板...');
|
||
|
||
// 渲染刷新摘要页面
|
||
try {
|
||
await this.render('panel/refresh.html', finalData);
|
||
} catch (renderError) {
|
||
logger.error('[panel.js] 渲染 refresh.html 模板失败:', renderError);
|
||
await this.reply(`生成刷新结果图片时出错: ${renderError.message}`);
|
||
}
|
||
}
|
||
|
||
async getCharPanelListTool(uid, origin = false) {
|
||
if (!uid) {
|
||
return false;
|
||
}
|
||
if (origin) {
|
||
const result = getPanelListOrigin(uid);
|
||
return result;
|
||
}
|
||
const result = getPanelList(uid);
|
||
return result;
|
||
}
|
||
|
||
async getCharPanel() {
|
||
const uid = await this.getUID();
|
||
const reg = new RegExp(`${rulePrefix}(.+)面板$`);
|
||
const match = this.e.msg.match(reg);
|
||
if (!match) return false;
|
||
const name = match[4];
|
||
const data = getPanelOrigin(uid, name);
|
||
if (!data) {
|
||
await this.reply(`未找到角色${name}的面板信息,请先刷新面板`);
|
||
return;
|
||
}
|
||
let handler = this.e.runtime.handler || {};
|
||
|
||
if (handler.has('zzz.tool.panel')) {
|
||
await handler.call('zzz.tool.panel', this.e, {
|
||
uid,
|
||
data: data,
|
||
needSave: false,
|
||
});
|
||
}
|
||
return false;
|
||
}
|
||
|
||
async getCharPanelTool(e, _data = {}) {
|
||
if (e) this.e = e;
|
||
if (e?.reply) this.reply = e.reply;
|
||
|
||
const {
|
||
uid = undefined,
|
||
data = undefined,
|
||
needSave = true,
|
||
reply = true,
|
||
needImg = true
|
||
} = _data;
|
||
if (!uid) {
|
||
await this.reply('UID为空');
|
||
return false;
|
||
}
|
||
if (!data) {
|
||
await this.reply('数据为空');
|
||
return false;
|
||
}
|
||
if (needSave) {
|
||
updatePanelData(uid, [data]);
|
||
}
|
||
const timer = setTimeout(() => {
|
||
const msg = '查询成功,正在下载图片资源,请稍候。'
|
||
if (this?.reply && needImg) {
|
||
this.reply(msg);
|
||
} else {
|
||
logger.mark(msg)
|
||
}
|
||
}, 5000);
|
||
const parsedData = formatPanelData(data);
|
||
await parsedData.get_detail_assets();
|
||
clearTimeout(timer);
|
||
const finalData = {
|
||
uid,
|
||
charData: parsedData,
|
||
};
|
||
const image = needImg ? await this.render('panel/card.html', finalData, {
|
||
retType: 'base64',
|
||
}) : needImg;
|
||
|
||
if (reply) {
|
||
const res = await this.reply(image);
|
||
if (res?.message_id && parsedData.role_icon)
|
||
await redis.set(
|
||
`ZZZ:PANEL:IMAGE:${res.message_id}`,
|
||
parsedData.role_icon,
|
||
{
|
||
EX: 3600 * 3,
|
||
}
|
||
);
|
||
return {
|
||
message: res,
|
||
image,
|
||
};
|
||
}
|
||
|
||
return image;
|
||
}
|
||
async proficiency() {
|
||
const uid = await this.getUID();
|
||
const result = getPanelList(uid);
|
||
if (!result) {
|
||
await this.reply('未找到面板数据,请先%刷新面板');
|
||
return false;
|
||
}
|
||
await this.getPlayerInfo();
|
||
result.sort((a, b) => {
|
||
return b.proficiency_score - a.proficiency_score;
|
||
});
|
||
const WeaponCount = result.filter(item => item?.weapon).length,
|
||
SWeaponCount = result.filter(
|
||
item => item?.weapon && item.weapon.rarity === 'S'
|
||
).length;
|
||
const general = {
|
||
total: result.length,
|
||
SCount: result.filter(item => item.rarity === 'S').length,
|
||
SWeaponRate: (SWeaponCount / WeaponCount) * 100,
|
||
SSSCount: result.reduce((acc, item) => {
|
||
if (item.equip) {
|
||
acc += item.equip.filter(
|
||
equip => equip.comment === 'SSS' || equip.comment === 'ACE'
|
||
).length;
|
||
}
|
||
return acc;
|
||
}, 0),
|
||
highRank: result.filter(item => item.rank > 4).length,
|
||
};
|
||
const timer = setTimeout(() => {
|
||
if (this?.reply) {
|
||
this.reply('查询成功,正在下载图片资源,请稍候。');
|
||
}
|
||
}, 5000);
|
||
for (const item of result) {
|
||
await item.get_small_basic_assets();
|
||
}
|
||
clearTimeout(timer);
|
||
const finalData = {
|
||
general,
|
||
list: result,
|
||
};
|
||
await this.render('proficiency/index.html', finalData);
|
||
}
|
||
async getCharOriImage() {
|
||
let source;
|
||
if (this.e.getReply) {
|
||
source = await this.e.getReply();
|
||
} else if (this.e.source) {
|
||
if (this.e.group?.getChatHistory) {
|
||
// 支持at图片添加,以及支持后发送
|
||
source = (
|
||
await this.e.group.getChatHistory(this.e.source?.seq, 1)
|
||
).pop();
|
||
} else if (this.e.friend?.getChatHistory) {
|
||
source = (
|
||
await this.e.friend.getChatHistory(this.e.source?.time + 1, 1)
|
||
).pop();
|
||
}
|
||
}
|
||
const id = source?.message_id;
|
||
if (!id) {
|
||
await this.reply('未找到消息源,请引用要查看的图片');
|
||
return false;
|
||
}
|
||
const image = await redis.get(`ZZZ:PANEL:IMAGE:${id}`);
|
||
if (!image) {
|
||
await this.reply('未找到原图');
|
||
return false;
|
||
}
|
||
await this.reply(segment.image(image));
|
||
return false;
|
||
}
|
||
}
|