mirror of
https://github.com/ZZZure/ZZZ-Plugin.git
synced 2025-12-16 21:27:47 +00:00
尝试解决图片第一次下载失败后无法自动解决图片裂开问题&驱动盘序号错位问题
This commit is contained in:
parent
8304b8bffa
commit
839ca76855
6 changed files with 153 additions and 56 deletions
|
|
@ -1,10 +1,10 @@
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import fetch from 'node-fetch';
|
|
||||||
import { ZZZ_SQUARE_AVATAR, ZZZ_SQUARE_BANGBOO } from './mysapi/api.js';
|
import { ZZZ_SQUARE_AVATAR, ZZZ_SQUARE_BANGBOO } from './mysapi/api.js';
|
||||||
import { imageResourcesPath } from './path.js';
|
import { imageResourcesPath } from './path.js';
|
||||||
import { char, equip, weapon } from './convert.js';
|
import { char, equip, weapon } from './convert.js';
|
||||||
import { getResourceRemotePath } from './assets.js';
|
import { getResourceRemotePath } from './assets.js';
|
||||||
|
import request from '../utils/request.js';
|
||||||
|
|
||||||
const ZZZ_SQUARE_AVATAR_PATH = path.join(imageResourcesPath, 'square_avatar');
|
const ZZZ_SQUARE_AVATAR_PATH = path.join(imageResourcesPath, 'square_avatar');
|
||||||
const ZZZ_SMALL_SQUARE_AVATAR_PATH = path.join(
|
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} url 下载地址
|
||||||
* @param {string} savePath 保存路径
|
* @param {string} savePath 保存路径
|
||||||
* @returns
|
* @returns {Promise<string | null>} 保存路径
|
||||||
*/
|
*/
|
||||||
export const downloadFile = async (url, savePath) => {
|
export const downloadFile = async (url, savePath) => {
|
||||||
const _download = async (url, savePath, retry = 0) => {
|
// 下载文件
|
||||||
// 重试次数超过 5 次则返回 null
|
try {
|
||||||
if (retry > 5) {
|
const download = await request(url, {}, 5);
|
||||||
return null;
|
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);
|
||||||
try {
|
// 返回保存路径
|
||||||
const download = await fetch(url);
|
return savePath;
|
||||||
const arrayBuffer = await download.arrayBuffer();
|
} catch (error) {
|
||||||
const buffer = Buffer.from(arrayBuffer);
|
return null;
|
||||||
// 保存文件
|
}
|
||||||
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);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -62,7 +54,12 @@ export const downloadFile = async (url, savePath) => {
|
||||||
export const getSquareAvatar = async charID => {
|
export const getSquareAvatar = async charID => {
|
||||||
const filename = `role_square_avatar_${charID}.png`;
|
const filename = `role_square_avatar_${charID}.png`;
|
||||||
const avatarPath = path.join(ZZZ_SQUARE_AVATAR_PATH, filename);
|
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 url = `${ZZZ_SQUARE_AVATAR}/${filename}`;
|
||||||
const savePath = avatarPath;
|
const savePath = avatarPath;
|
||||||
const download = await downloadFile(url, savePath);
|
const download = await downloadFile(url, savePath);
|
||||||
|
|
@ -80,7 +77,12 @@ export const getSmallSquareAvatar = async charID => {
|
||||||
if (!sprite) return null;
|
if (!sprite) return null;
|
||||||
const filename = `IconRoleGeneral${sprite}.png`;
|
const filename = `IconRoleGeneral${sprite}.png`;
|
||||||
const avatarPath = path.join(ZZZ_SMALL_SQUARE_AVATAR_PATH, filename);
|
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 url = await getResourceRemotePath('role_general', filename);
|
||||||
const savePath = avatarPath;
|
const savePath = avatarPath;
|
||||||
const download = await downloadFile(url, savePath);
|
const download = await downloadFile(url, savePath);
|
||||||
|
|
@ -95,7 +97,12 @@ export const getSmallSquareAvatar = async charID => {
|
||||||
export const getSquareBangboo = async bangbooId => {
|
export const getSquareBangboo = async bangbooId => {
|
||||||
const filename = `bangboo_rectangle_avatar_${bangbooId}.png`;
|
const filename = `bangboo_rectangle_avatar_${bangbooId}.png`;
|
||||||
const bangbooPath = path.join(ZZZ_SQUARE_BANGBOO_PATH, filename);
|
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 url = `${ZZZ_SQUARE_BANGBOO}/${filename}`;
|
||||||
const savePath = bangbooPath;
|
const savePath = bangbooPath;
|
||||||
const download = await downloadFile(url, savePath);
|
const download = await downloadFile(url, savePath);
|
||||||
|
|
@ -111,7 +118,12 @@ export const getWeaponImage = async id => {
|
||||||
const name = weapon.IDToWeaponFileName(id);
|
const name = weapon.IDToWeaponFileName(id);
|
||||||
const filename = `${name}.png`;
|
const filename = `${name}.png`;
|
||||||
const weaponPath = path.join(ZZZ_WEAPON_PATH, filename);
|
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 url = await getResourceRemotePath('weapon', filename);
|
||||||
const savePath = weaponPath;
|
const savePath = weaponPath;
|
||||||
const download = await downloadFile(url, savePath);
|
const download = await downloadFile(url, savePath);
|
||||||
|
|
@ -128,7 +140,12 @@ export const getRoleImage = async id => {
|
||||||
if (!sprite) return null;
|
if (!sprite) return null;
|
||||||
const filename = `IconRole${sprite}.png`;
|
const filename = `IconRole${sprite}.png`;
|
||||||
const rolePath = path.join(ZZZ_ROLE_PATH, filename);
|
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 url = await getResourceRemotePath('role', filename);
|
||||||
const savePath = rolePath;
|
const savePath = rolePath;
|
||||||
const download = await downloadFile(url, savePath);
|
const download = await downloadFile(url, savePath);
|
||||||
|
|
@ -145,7 +162,12 @@ export const getRoleCircleImage = async id => {
|
||||||
if (!sprite) return null;
|
if (!sprite) return null;
|
||||||
const filename = `IconRoleCircle${sprite}.png`;
|
const filename = `IconRoleCircle${sprite}.png`;
|
||||||
const roleCirclePath = path.join(ZZZ_ROLE_CIRCLE_PATH, filename);
|
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 url = await getResourceRemotePath('role_circle', filename);
|
||||||
const savePath = roleCirclePath;
|
const savePath = roleCirclePath;
|
||||||
const download = await downloadFile(url, savePath);
|
const download = await downloadFile(url, savePath);
|
||||||
|
|
@ -161,7 +183,12 @@ export const getSuitImage = async suitId => {
|
||||||
const suitName = equip.equipIdToSprite(suitId);
|
const suitName = equip.equipIdToSprite(suitId);
|
||||||
const filename = `${suitName}.png`;
|
const filename = `${suitName}.png`;
|
||||||
const suitPath = path.join(ZZZ_SUIT_PATH, filename);
|
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 url = await getResourceRemotePath('suit', filename);
|
||||||
const savePath = suitPath;
|
const savePath = suitPath;
|
||||||
const download = await downloadFile(url, savePath);
|
const download = await downloadFile(url, savePath);
|
||||||
|
|
@ -177,7 +204,12 @@ export const getSuit3DImage = async suitId => {
|
||||||
const suitName = equip.equipIdToSprite(suitId);
|
const suitName = equip.equipIdToSprite(suitId);
|
||||||
const filename = `${suitName}_3d.png`;
|
const filename = `${suitName}_3d.png`;
|
||||||
const suitPath = path.join(ZZZ_SUIT_3D_PATH, filename);
|
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 url = await getResourceRemotePath('suit_3d', filename);
|
||||||
const savePath = suitPath;
|
const savePath = suitPath;
|
||||||
const download = await downloadFile(url, savePath);
|
const download = await downloadFile(url, savePath);
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import { sleep } from '../utils/time.js';
|
||||||
import { rank } from './convert.js';
|
import { rank } from './convert.js';
|
||||||
import { getGachaLog, saveGachaLog } from './db.js';
|
import { getGachaLog, saveGachaLog } from './db.js';
|
||||||
import { ZZZ_GET_GACHA_LOG_API } from './mysapi/api.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 = {
|
export const gacha_type_meta_data = {
|
||||||
|
|
@ -121,11 +121,12 @@ export const getZZZGachaLogByAuthkey = async (
|
||||||
endId
|
endId
|
||||||
);
|
);
|
||||||
// 发送请求
|
// 发送请求
|
||||||
const response = await fetchWithRetry(link, {
|
const response = await request(link, {
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
},
|
},
|
||||||
|
retry: 3,
|
||||||
});
|
});
|
||||||
// 获取数据
|
// 获取数据
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
|
|
|
||||||
|
|
@ -474,6 +474,17 @@ export class ZZZAvatarInfo {
|
||||||
return score;
|
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<void>}
|
* @returns {Promise<void>}
|
||||||
|
|
|
||||||
|
|
@ -150,7 +150,8 @@
|
||||||
</div>
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
<div class="equip-list">
|
<div class="equip-list">
|
||||||
{{each charData.equip equip}}
|
{{each charData.equip_final equip}}
|
||||||
|
{{if equip}}
|
||||||
<div class="box">
|
<div class="box">
|
||||||
<div class="icon">
|
<div class="icon">
|
||||||
<img src="{{equip.suit_icon}}" alt="">
|
<img src="{{equip.suit_icon}}" alt="">
|
||||||
|
|
@ -199,13 +200,14 @@
|
||||||
{{/each}}
|
{{/each}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{/each}}
|
{{else}}
|
||||||
<% for(let i=charData.equip.length; i < 6 ; i++) { %>
|
|
||||||
<div class="box empty">
|
<div class="box empty">
|
||||||
<div class="icon">
|
<div class="icon">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<% } %>
|
{{/if}}
|
||||||
|
|
||||||
|
{{/each}}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
{{if charData?.damages && charData?.damages?.length}}
|
{{if charData?.damages && charData?.damages?.length}}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
import http from 'http';
|
import http from 'http';
|
||||||
import https from 'https';
|
import https from 'https';
|
||||||
import fetch from 'node-fetch';
|
|
||||||
export async function checkLatency(url) {
|
export async function checkLatency(url) {
|
||||||
let request = http;
|
let request = http;
|
||||||
if (url.startsWith('https')) {
|
if (url.startsWith('https')) {
|
||||||
|
|
@ -36,20 +35,3 @@ export function getQueryVariable(url, variable) {
|
||||||
const key = searchParams.get(variable);
|
const key = searchParams.get(variable);
|
||||||
return key;
|
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);
|
|
||||||
}
|
|
||||||
|
|
|
||||||
69
utils/request.js
Normal file
69
utils/request.js
Normal file
|
|
@ -0,0 +1,69 @@
|
||||||
|
import fetch from 'node-fetch';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 请求
|
||||||
|
* @param {string} url 请求地址
|
||||||
|
* @param {object} options 请求配置
|
||||||
|
* @returns {Promise<Response>}
|
||||||
|
*/
|
||||||
|
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<Response>}
|
||||||
|
*/
|
||||||
|
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<Response>}
|
||||||
|
*/
|
||||||
|
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<Response>}
|
||||||
|
*/
|
||||||
|
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;
|
||||||
Loading…
Add table
Add a link
Reference in a new issue