chore:AI大修改
This commit is contained in:
@@ -6,7 +6,29 @@ import fs from "node:fs";
|
||||
import fse from "fs-extra";
|
||||
import { WebSocket } from "ws";
|
||||
import { ExecOptions, exec} from "node:child_process";
|
||||
|
||||
/**
|
||||
* Java版本信息接口
|
||||
*/
|
||||
export interface JavaVersion {
|
||||
major: number;
|
||||
minor: number;
|
||||
patch: number;
|
||||
fullVersion: string;
|
||||
vendor: string;
|
||||
runtimeVersion?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Java检测结果接口
|
||||
*/
|
||||
export interface JavaCheckResult {
|
||||
exists: boolean;
|
||||
version?: JavaVersion;
|
||||
error?: string;
|
||||
}
|
||||
import { MessageWS } from "./ws.js";
|
||||
import { logger } from "./logger.js";
|
||||
|
||||
export class Utils {
|
||||
public modrinth_url: string;
|
||||
@@ -50,90 +72,157 @@ export function version_compare(v1: string, v2: string) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检测Java是否安装并获取版本信息
|
||||
* @returns Java检测结果
|
||||
*/
|
||||
export async function checkJava(): Promise<JavaCheckResult> {
|
||||
try {
|
||||
const output = await new Promise<string>((resolve, reject) => {
|
||||
exec("java -version", (err, stdout, stderr) => {
|
||||
if (err) {
|
||||
logger.error("Java check failed", err);
|
||||
reject(new Error("Java not found"));
|
||||
return;
|
||||
}
|
||||
// Java版本信息输出在stderr中
|
||||
resolve(stderr);
|
||||
});
|
||||
});
|
||||
|
||||
logger.debug(`Java version output: ${output}`);
|
||||
|
||||
// 解析Java版本信息
|
||||
const versionRegex = /version "(\d+)(\.(\d+))?(\.(\d+))?/;
|
||||
const vendorRegex = /(Java\(TM\)|OpenJDK).*Runtime Environment.*by (.*)/;
|
||||
|
||||
const versionMatch = output.match(versionRegex);
|
||||
const vendorMatch = output.match(vendorRegex);
|
||||
|
||||
if (!versionMatch) {
|
||||
return {
|
||||
exists: true,
|
||||
error: "Failed to parse Java version"
|
||||
};
|
||||
}
|
||||
|
||||
const major = parseInt(versionMatch[1], 10);
|
||||
const minor = versionMatch[3] ? parseInt(versionMatch[3], 10) : 0;
|
||||
const patch = versionMatch[5] ? parseInt(versionMatch[5], 10) : 0;
|
||||
|
||||
const versionInfo: JavaVersion = {
|
||||
major,
|
||||
minor,
|
||||
patch,
|
||||
fullVersion: versionMatch[0].replace("version ", ""),
|
||||
vendor: vendorMatch ? vendorMatch[2] : "Unknown"
|
||||
};
|
||||
|
||||
logger.info(`Java detected: ${JSON.stringify(versionInfo)}`);
|
||||
|
||||
return {
|
||||
exists: true,
|
||||
version: versionInfo
|
||||
};
|
||||
} catch (error) {
|
||||
logger.error("Java check error", error as Error);
|
||||
return {
|
||||
exists: false,
|
||||
error: (error as Error).message
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export function execPromise(cmd:string,options?:ExecOptions){
|
||||
logger.debug(`Executing command: ${cmd}`);
|
||||
return new Promise((resolve,reject)=>{
|
||||
exec(cmd,options,(err,stdout,stderr)=>{
|
||||
if(err){
|
||||
logger.error(`Command execution failed: ${cmd}`, err);
|
||||
logger.debug(`Stderr: ${stderr}`);
|
||||
reject(err)
|
||||
return;
|
||||
}
|
||||
if (stdout) logger.debug(`Command stdout: ${stdout}`);
|
||||
if (stderr) logger.debug(`Command stderr: ${stderr}`);
|
||||
}).on('exit',(code)=>{
|
||||
logger.debug(`Command completed with exit code: ${code}`);
|
||||
resolve(code)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
export async function fastdownload(data: [string, string]|string[][]) {
|
||||
let _data = undefined;
|
||||
if(Array.isArray(data[0])){
|
||||
_data = data
|
||||
}else{
|
||||
_data = [data]
|
||||
}
|
||||
// 确保downloadList始终是[string, string][]类型
|
||||
const downloadList: [string, string][] = Array.isArray(data[0])
|
||||
? (data as string[][]).map(item => item as [string, string])
|
||||
: [data as [string, string]];
|
||||
logger.info(`Starting fast download of ${downloadList.length} files`);
|
||||
|
||||
return await pMap(
|
||||
_data,
|
||||
async (e:any) => {
|
||||
downloadList,
|
||||
async (item: [string, string]) => {
|
||||
const [url, filePath] = item;
|
||||
try {
|
||||
await pRetry(
|
||||
async () => {
|
||||
if (!fs.existsSync(e[1])) {
|
||||
await got
|
||||
.get(e[0], {
|
||||
responseType: "buffer",
|
||||
headers: {
|
||||
"user-agent": "DeEarthX",
|
||||
},
|
||||
})
|
||||
.then((res) => {
|
||||
fse.outputFileSync(e[1], res.rawBody);
|
||||
});
|
||||
if (!fs.existsSync(filePath)) {
|
||||
logger.debug(`Downloading ${url} to ${filePath}`);
|
||||
const res = await got.get(url, {
|
||||
responseType: "buffer",
|
||||
headers: { "user-agent": "DeEarthX" },
|
||||
});
|
||||
fse.outputFileSync(filePath, res.rawBody);
|
||||
logger.debug(`Downloaded ${url} successfully`);
|
||||
} else {
|
||||
logger.debug(`File already exists, skipping: ${filePath}`);
|
||||
}
|
||||
},
|
||||
{ retries: 3 }
|
||||
{ retries: 3, onFailedAttempt: (error) => {
|
||||
logger.warn(`Download attempt failed for ${url}, retrying (${error.attemptNumber}/3)`);
|
||||
}}
|
||||
);
|
||||
} catch (e) {
|
||||
//LOGGER.error({ err: e });
|
||||
} catch (error) {
|
||||
logger.error(`Failed to download ${url} after 3 attempts`, error);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
{ concurrency: 16 }
|
||||
);
|
||||
}
|
||||
|
||||
export async function Wfastdownload(data: string[][],ws:MessageWS) {
|
||||
let index = 1;
|
||||
export async function Wfastdownload(data: string[][], ws: MessageWS) {
|
||||
logger.info(`Starting web download of ${data.length} files`);
|
||||
|
||||
return await pMap(
|
||||
data,
|
||||
async (e:any) => {
|
||||
async (item: string[], idx: number) => {
|
||||
const [url, filePath] = item;
|
||||
try {
|
||||
await pRetry(
|
||||
async () => {
|
||||
if (!fs.existsSync(e[1])) {
|
||||
await got
|
||||
.get(e[0], {
|
||||
responseType: "buffer",
|
||||
headers: {
|
||||
"user-agent": "DeEarthX",
|
||||
},
|
||||
})
|
||||
.then((res) => {
|
||||
fse.outputFileSync(e[1], res.rawBody);
|
||||
});
|
||||
if (!fs.existsSync(filePath)) {
|
||||
logger.debug(`Downloading ${url} to ${filePath}`);
|
||||
const res = await got.get(url, {
|
||||
responseType: "buffer",
|
||||
headers: { "user-agent": "DeEarthX" },
|
||||
});
|
||||
fse.outputFileSync(filePath, res.rawBody);
|
||||
logger.debug(`Downloaded ${url} successfully`);
|
||||
} else {
|
||||
logger.debug(`File already exists, skipping: ${filePath}`);
|
||||
}
|
||||
ws.download(data.length,index,e[1])
|
||||
// ws.send(JSON.stringify({
|
||||
// status:"downloading",
|
||||
// result:{
|
||||
// total:data.length,
|
||||
// index:index,
|
||||
// name:e[1]
|
||||
// }
|
||||
// }))
|
||||
index++
|
||||
|
||||
// 更新下载进度
|
||||
ws.download(data.length, idx + 1, filePath);
|
||||
},
|
||||
{ retries: 3 }
|
||||
{ retries: 3, onFailedAttempt: (error) => {
|
||||
logger.warn(`Download attempt failed for ${url}, retrying (${error.attemptNumber}/3)`);
|
||||
}}
|
||||
);
|
||||
} catch (e) {
|
||||
//LOGGER.error({ err: e });
|
||||
} catch (error) {
|
||||
logger.error(`Failed to download ${url} after 3 attempts`, error);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
{ concurrency: 16 }
|
||||
|
||||
Reference in New Issue
Block a user