From 839ca7685517f03ecd2abf1f683db84f16d0a4b9 Mon Sep 17 00:00:00 2001 From: bietiaop <1527109126@qq.com> Date: Wed, 14 Aug 2024 20:46:13 +0800 Subject: [PATCH] =?UTF-8?q?=E5=B0=9D=E8=AF=95=E8=A7=A3=E5=86=B3=E5=9B=BE?= =?UTF-8?q?=E7=89=87=E7=AC=AC=E4=B8=80=E6=AC=A1=E4=B8=8B=E8=BD=BD=E5=A4=B1?= =?UTF-8?q?=E8=B4=A5=E5=90=8E=E6=97=A0=E6=B3=95=E8=87=AA=E5=8A=A8=E8=A7=A3?= =?UTF-8?q?=E5=86=B3=E5=9B=BE=E7=89=87=E8=A3=82=E5=BC=80=E9=97=AE=E9=A2=98?= =?UTF-8?q?&=E9=A9=B1=E5=8A=A8=E7=9B=98=E5=BA=8F=E5=8F=B7=E9=94=99?= =?UTF-8?q?=E4=BD=8D=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/download.js | 96 ++++++++++++++++++++++++++------------- lib/gacha.js | 5 +- model/avatar.js | 11 +++++ resources/panel/card.html | 10 ++-- utils/network.js | 18 -------- utils/request.js | 69 ++++++++++++++++++++++++++++ 6 files changed, 153 insertions(+), 56 deletions(-) create mode 100644 utils/request.js diff --git a/lib/download.js b/lib/download.js index 5c3dc27..ea736f6 100644 --- a/lib/download.js +++ b/lib/download.js @@ -1,10 +1,10 @@ import path from 'path'; import fs from 'fs'; -import fetch from 'node-fetch'; import { ZZZ_SQUARE_AVATAR, ZZZ_SQUARE_BANGBOO } from './mysapi/api.js'; import { imageResourcesPath } from './path.js'; import { char, equip, weapon } from './convert.js'; import { getResourceRemotePath } from './assets.js'; +import request from '../utils/request.js'; const ZZZ_SQUARE_AVATAR_PATH = path.join(imageResourcesPath, 'square_avatar'); const ZZZ_SMALL_SQUARE_AVATAR_PATH = path.join( @@ -26,32 +26,24 @@ const ZZZ_SUIT_PATH = path.join(imageResourcesPath, 'suit'); * 下载文件 * @param {string} url 下载地址 * @param {string} savePath 保存路径 - * @returns + * @returns {Promise} 保存路径 */ export const downloadFile = async (url, savePath) => { - const _download = async (url, savePath, retry = 0) => { - // 重试次数超过 5 次则返回 null - if (retry > 5) { - return null; + // 下载文件 + try { + const download = await request(url, {}, 5); + const arrayBuffer = await download.arrayBuffer(); + const buffer = Buffer.from(arrayBuffer); + // 保存文件 + if (!fs.existsSync(path.dirname(savePath))) { + fs.mkdirSync(path.dirname(savePath), { recursive: true }); } - // 下载文件 - try { - const download = await fetch(url); - const arrayBuffer = await download.arrayBuffer(); - const buffer = Buffer.from(arrayBuffer); - // 保存文件 - if (!fs.existsSync(path.dirname(savePath))) { - fs.mkdirSync(path.dirname(savePath), { recursive: true }); - } - fs.writeFileSync(savePath, buffer); - // 返回保存路径 - return savePath; - } catch (error) { - // 下载失败,重试 - return await _download(url, savePath, retry + 1); - } - }; - return await _download(url, savePath); + fs.writeFileSync(savePath, buffer); + // 返回保存路径 + return savePath; + } catch (error) { + return null; + } }; /** @@ -62,7 +54,12 @@ export const downloadFile = async (url, savePath) => { export const getSquareAvatar = async charID => { const filename = `role_square_avatar_${charID}.png`; const avatarPath = path.join(ZZZ_SQUARE_AVATAR_PATH, filename); - if (fs.existsSync(avatarPath)) return avatarPath; + if (fs.existsSync(avatarPath)) { + const stats = fs.statSync(avatarPath); + if (stats.size > 0) { + return avatarPath; + } + } const url = `${ZZZ_SQUARE_AVATAR}/${filename}`; const savePath = avatarPath; const download = await downloadFile(url, savePath); @@ -80,7 +77,12 @@ export const getSmallSquareAvatar = async charID => { if (!sprite) return null; const filename = `IconRoleGeneral${sprite}.png`; const avatarPath = path.join(ZZZ_SMALL_SQUARE_AVATAR_PATH, filename); - if (fs.existsSync(avatarPath)) return avatarPath; + if (fs.existsSync(avatarPath)) { + const stats = fs.statSync(avatarPath); + if (stats.size > 0) { + return avatarPath; + } + } const url = await getResourceRemotePath('role_general', filename); const savePath = avatarPath; const download = await downloadFile(url, savePath); @@ -95,7 +97,12 @@ export const getSmallSquareAvatar = async charID => { export const getSquareBangboo = async bangbooId => { const filename = `bangboo_rectangle_avatar_${bangbooId}.png`; const bangbooPath = path.join(ZZZ_SQUARE_BANGBOO_PATH, filename); - if (fs.existsSync(bangbooPath)) return bangbooPath; + if (fs.existsSync(bangbooPath)) { + const stats = fs.statSync(bangbooPath); + if (stats.size > 0) { + return bangbooPath; + } + } const url = `${ZZZ_SQUARE_BANGBOO}/${filename}`; const savePath = bangbooPath; const download = await downloadFile(url, savePath); @@ -111,7 +118,12 @@ export const getWeaponImage = async id => { const name = weapon.IDToWeaponFileName(id); const filename = `${name}.png`; const weaponPath = path.join(ZZZ_WEAPON_PATH, filename); - if (fs.existsSync(weaponPath)) return weaponPath; + if (fs.existsSync(weaponPath)) { + const stats = fs.statSync(weaponPath); + if (stats.size > 0) { + return weaponPath; + } + } const url = await getResourceRemotePath('weapon', filename); const savePath = weaponPath; const download = await downloadFile(url, savePath); @@ -128,7 +140,12 @@ export const getRoleImage = async id => { if (!sprite) return null; const filename = `IconRole${sprite}.png`; const rolePath = path.join(ZZZ_ROLE_PATH, filename); - if (fs.existsSync(rolePath)) return rolePath; + if (fs.existsSync(rolePath)) { + const stats = fs.statSync(rolePath); + if (stats.size > 0) { + return rolePath; + } + } const url = await getResourceRemotePath('role', filename); const savePath = rolePath; const download = await downloadFile(url, savePath); @@ -145,7 +162,12 @@ export const getRoleCircleImage = async id => { if (!sprite) return null; const filename = `IconRoleCircle${sprite}.png`; const roleCirclePath = path.join(ZZZ_ROLE_CIRCLE_PATH, filename); - if (fs.existsSync(roleCirclePath)) return roleCirclePath; + if (fs.existsSync(roleCirclePath)) { + const stats = fs.statSync(roleCirclePath); + if (stats.size > 0) { + return roleCirclePath; + } + } const url = await getResourceRemotePath('role_circle', filename); const savePath = roleCirclePath; const download = await downloadFile(url, savePath); @@ -161,7 +183,12 @@ export const getSuitImage = async suitId => { const suitName = equip.equipIdToSprite(suitId); const filename = `${suitName}.png`; const suitPath = path.join(ZZZ_SUIT_PATH, filename); - if (fs.existsSync(suitPath)) return suitPath; + if (fs.existsSync(suitPath)) { + const stats = fs.statSync(suitPath); + if (stats.size > 0) { + return suitPath; + } + } const url = await getResourceRemotePath('suit', filename); const savePath = suitPath; const download = await downloadFile(url, savePath); @@ -177,7 +204,12 @@ export const getSuit3DImage = async suitId => { const suitName = equip.equipIdToSprite(suitId); const filename = `${suitName}_3d.png`; const suitPath = path.join(ZZZ_SUIT_3D_PATH, filename); - if (fs.existsSync(suitPath)) return suitPath; + if (fs.existsSync(suitPath)) { + const stats = fs.statSync(suitPath); + if (stats.size > 0) { + return suitPath; + } + } const url = await getResourceRemotePath('suit_3d', filename); const savePath = suitPath; const download = await downloadFile(url, savePath); diff --git a/lib/gacha.js b/lib/gacha.js index 9b91cdc..01b174e 100644 --- a/lib/gacha.js +++ b/lib/gacha.js @@ -3,7 +3,7 @@ import { sleep } from '../utils/time.js'; import { rank } from './convert.js'; import { getGachaLog, saveGachaLog } from './db.js'; import { ZZZ_GET_GACHA_LOG_API } from './mysapi/api.js'; -import { fetchWithRetry } from '../utils/network.js'; +import request from '../utils/request.js'; // 池子代码 export const gacha_type_meta_data = { @@ -121,11 +121,12 @@ export const getZZZGachaLogByAuthkey = async ( endId ); // 发送请求 - const response = await fetchWithRetry(link, { + const response = await request(link, { method: 'GET', headers: { 'Content-Type': 'application/json', }, + retry: 3, }); // 获取数据 const data = await response.json(); diff --git a/model/avatar.js b/model/avatar.js index 5aadac0..7f421df 100644 --- a/model/avatar.js +++ b/model/avatar.js @@ -474,6 +474,17 @@ export class ZZZAvatarInfo { return score; } + /** @type {Equip[]} equip_final */ + get equip_final() { + const result = []; + this.equip.forEach(equip => { + if (equip.equipment_type) { + result[equip.equipment_type - 1] = equip; + } + }); + return result; + } + /** * 获取基础资源 * @returns {Promise} diff --git a/resources/panel/card.html b/resources/panel/card.html index a12c01c..9946048 100644 --- a/resources/panel/card.html +++ b/resources/panel/card.html @@ -150,7 +150,8 @@ {{/if}}
- {{each charData.equip equip}} + {{each charData.equip_final equip}} + {{if equip}}
@@ -199,13 +200,14 @@ {{/each}}
- {{/each}} - <% for(let i=charData.equip.length; i < 6 ; i++) { %> + {{else}}
- <% } %> + {{/if}} + + {{/each}}
{{if charData?.damages && charData?.damages?.length}} diff --git a/utils/network.js b/utils/network.js index a817abc..b4eb275 100644 --- a/utils/network.js +++ b/utils/network.js @@ -1,6 +1,5 @@ import http from 'http'; import https from 'https'; -import fetch from 'node-fetch'; export async function checkLatency(url) { let request = http; if (url.startsWith('https')) { @@ -36,20 +35,3 @@ export function getQueryVariable(url, variable) { const key = searchParams.get(variable); return key; } - -export async function fetchWithRetry(url, options, retry = 3) { - let err; - const _fetch = async (url, options, retryCount = 0) => { - if (retryCount > retry) { - throw new Error('Retry limit reached', err); - } - try { - return await fetch(url, options); - } catch (error) { - logger.debug(`Fetch error: ${error.message}`); - err = error; - return _fetch(url, options, retryCount + 1); - } - }; - return _fetch(url, options); -} diff --git a/utils/request.js b/utils/request.js new file mode 100644 index 0000000..e728ab8 --- /dev/null +++ b/utils/request.js @@ -0,0 +1,69 @@ +import fetch from 'node-fetch'; + +/** + * 请求 + * @param {string} url 请求地址 + * @param {object} options 请求配置 + * @returns {Promise} + */ +const _request = async (url, options) => { + const response = await fetch(url, options); + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } else if (response.status < 200 || response.status >= 300) { + throw new Error(`HTTP error! status: ${response.status}`); + } + return response; +}; + +/** + * 请求 + * @param {string} url 请求地址 + * @param {object} options 请求配置 + * @param {number} retry 重试次数 + * @returns {Promise} + */ +const request = (url, options, retry = 0) => { + let err; + const _fetch = async (url, options, retryCount = 0) => { + if (retryCount > retry) { + throw new Error('Retry limit reached', err); + } + try { + return await _request(url, options); + } catch (error) { + logger.debug(`Fetch error: ${error.message}`); + err = error; + return await _fetch(url, options, retryCount + 1); + } + }; + return _fetch(url, options); +}; + +/** + * GET 请求 + * @param {string} url 请求地址 + * @param {object} data 请求数据 + * @param {object} options 请求配置 + * @returns {Promise} + */ +request.get = async (url, data, options) => { + const params = new URLSearchParams(data); + const { retry, ...restOptions } = options; + return request(`${url}?${params}`, restOptions, retry); +}; + +/** + * POST 请求 + * @param {string} url 请求地址 + * @param {object} data 请求数据 + * @param {object} options 请求配置 + * @returns {Promise} + */ +request.post = async (url, data, options) => { + const body = JSON.stringify(data); + const { retry, ...restOptions } = options; + return request(url, { ...restOptions, method: 'POST', body }, retry); +}; + +export default request;