chore:人工修改屎山

This commit is contained in:
Tianpao
2025-12-27 14:23:34 +08:00
parent 6c3fbf0ae8
commit 03ed0a4cb7
11 changed files with 182 additions and 230 deletions

View File

@@ -1,5 +1,5 @@
import fs from "node:fs";
import p from "node:path"
import p from "node:path";
import websocket, { WebSocketServer } from "ws";
import { yauzl_promise } from "./utils/yauzl.promise.js";
import { pipeline } from "node:stream/promises";
@@ -8,103 +8,95 @@ import { DeEarth } from "./utils/DeEarth.js";
import { dinstall, mlsetup } from "./modloader/index.js";
import config from "./utils/config.js";
import { execPromise } from "./utils/utils.js";
import { MessageWS } from "./utils/ws.js";
import { debug } from "./utils/logger.js";
export class Dex {
wsx!: WebSocketServer;
in: any;
ws!: websocket;
message!: MessageWS;
constructor(ws: WebSocketServer) {
this.wsx = ws;
this.wsx.on("connection", (e) => {
this.ws = e;
this.message = new MessageWS(e);
});
this.in = {};
}
public async Main(buffer: Buffer, dser: boolean) {
try{
const first = Date.now();
const info = await this._getinfo(buffer).catch((e)=>{
throw new Error(e)
});
const plat = what_platform(info);
const mpname = this.in.name;
const unpath = `./instance/${mpname}`;
await Promise.all([
this._unzip(buffer, mpname),
await platform(plat).downloadfile(this.in, unpath, this.ws),
]).catch((e) => {
throw new Error(e)
}); // 解压和下载
this.ws.send(
JSON.stringify({
status: "changed",
result: undefined,
})
); //改变状态
await new DeEarth(`${unpath}/mods`, `./.rubbish/${mpname}`).Main().catch((e) => {
throw new Error(e)
});
this.ws.send(
JSON.stringify({
status: "changed",
result: undefined,
})
); //改变状态(DeEarth筛选模组完毕)
const mlinfo = await platform(plat).getinfo(this.in).catch((e)=>{
throw new Error(e)
});
if (dser) {
await mlsetup(
mlinfo.loader,
mlinfo.minecraft,
mlinfo.loader_version,
unpath
).catch((e) => {
throw new Error(e)
}); //安装服务端
}
if (!dser) {
dinstall(mlinfo.loader, mlinfo.minecraft, mlinfo.loader_version, unpath).catch((e) => {
throw new Error(e)
try {
const first = Date.now();
const { contain, info } = await this._getinfo(buffer).catch((e) => {
throw new Error(e);
});
const plat = what_platform(contain);
debug(plat);
debug(info);
const mpname = info.name;
const unpath = `./instance/${mpname}`;
await Promise.all([
this._unzip(buffer, mpname),
await platform(plat).downloadfile(info, unpath, this.message),
]).catch((e) => {
throw new Error(e);
}); // 解压和下载
this.message.statusChange(); //改变状态
await new DeEarth(`${unpath}/mods`, `./.rubbish/${mpname}`)
.Main()
.catch((e) => {
throw new Error(e);
});
this.message.statusChange(); //改变状态(DeEarth筛选模组完毕)
const mlinfo = await platform(plat)
.getinfo(info)
.catch((e) => {
throw new Error(e);
});
if (dser) {
await mlsetup(
mlinfo.loader,
mlinfo.minecraft,
mlinfo.loader_version,
unpath
).catch((e) => {
throw new Error(e);
}); //安装服务端
}
if (!dser) {
dinstall(
mlinfo.loader,
mlinfo.minecraft,
mlinfo.loader_version,
unpath
).catch((e) => {
throw new Error(e);
});
}
const latest = Date.now();
this.message.finish(first, latest); //完成
if (config.oaf) {
await execPromise(`start ${p.join("./instance")}`).catch((e) => {
throw new Error(e);
});
}
//await this._unzip(buffer);
} catch (e) {
const err = e as Error;
this.message.handleError(err);
}
const latest = Date.now();
this.ws.send(
JSON.stringify({
status: "finish",
result: latest - first,
})
);
if (config.oaf) {
await execPromise(`start ${p.join("./instance")}`).catch((e) => {
throw new Error(e)
});
}
//await this._unzip(buffer);
}catch(e){
const err = e as Error
this.ws.send(
JSON.stringify({
status: "error",
result: err.message,
})
);
}
}
private async _getinfo(buffer: Buffer) {
const important_name = ["manifest.json", "modrinth.index.json"];
let contain: string = "";
let info: any = {};
const zip = await yauzl_promise(buffer);
zip.forEach(async (e) => {
if (important_name.includes(e.fileName)) {
contain = e.fileName;
this.in = JSON.parse((await e.ReadEntry).toString());
return;
for await (const entry of zip) {
if (important_name.includes(entry.fileName)) {
contain = entry.fileName;
info = JSON.parse((await entry.ReadEntry).toString());
break;
}
});
return contain;
}
return { contain, info };
}
private async _unzip(buffer: Buffer, instancename: string) {
@@ -139,12 +131,13 @@ export class Dex {
);
await pipeline(stream, write);
}
this.ws.send(
JSON.stringify({
status: "unzip",
result: { name: entry.fileName, total: zip.length, current: index },
})
);
this.message.unzip(entry.fileName, zip.length, index);
// this.ws.send(
// JSON.stringify({
// status: "unzip",
// result: { name: entry.fileName, total: zip.length, current: index },
// })
// );
index++;
}
/* 解压完成 */

View File

@@ -1,6 +1,6 @@
import got, { Got } from "got";
import fs from "node:fs"
import { execPromise, fastdownload, xfastdownload } from "../utils/utils.js";
import { execPromise, fastdownload } from "../utils/utils.js";
interface ILatestLoader{
url:string,
@@ -56,7 +56,7 @@ export class Fabric{
const path = this.MTP(e.name)
_downlist.push([`https://bmclapi2.bangbang93.com/maven/${path}`,`${this.path}/libraries/${path}`])
})
await xfastdownload(_downlist)
await fastdownload(_downlist)
}
async installer(){

View File

@@ -1,7 +1,7 @@
import got, { Got } from "got";
import fs from "node:fs"
import fse from "fs-extra"
import { execPromise, fastdownload, version_compare, xfastdownload } from "../utils/utils.js";
import { execPromise, fastdownload, version_compare } from "../utils/utils.js";
import { yauzl_promise } from "../utils/yauzl.promise.js";
import { execSync } from "node:child_process";
@@ -76,7 +76,7 @@ export class Forge {
}
}
const downlist = [...new Set(_downlist)]
await xfastdownload(downlist)
await fastdownload(downlist)
}
async install(){

View File

@@ -1,10 +1,8 @@
import fs from "node:fs"
import pa from "node:path"
import { fastdownload, version_compare } from "../utils/utils.js";
import { yauzl_promise } from "../utils/yauzl.promise.js";
import { pipeline } from "node:stream/promises";
import got from "got";
import fsExtra from "fs-extra/esm";
interface ILInfo {
libraries: {

View File

@@ -3,6 +3,7 @@ import { WebSocket } from "ws";
import { join } from "node:path";
import { Wfastdownload, Utils } from "../utils/utils.js";
import { modpack_info, XPlatform } from "./index.js";
import { MessageWS } from "../utils/ws.js";
export interface CurseForgeManifest {
minecraft: {
@@ -39,7 +40,7 @@ export class CurseForge implements XPlatform {
return result;
}
async downloadfile(manifest: object, path: string, ws:WebSocket): Promise<void> {
async downloadfile(manifest: object, path: string, ws:MessageWS): Promise<void> {
const local_manifest = manifest as CurseForgeManifest;
if (local_manifest.files.length === 0){
return;
@@ -49,7 +50,7 @@ export class CurseForge implements XPlatform {
(file: { fileID: number }) => file.fileID
),
});
let tmp: [string, string] | string[][] = [];
let tmp: string[][] = [];
await this.got
.post("v1/mods/files", {
body: FileID,
@@ -64,17 +65,9 @@ export class CurseForge implements XPlatform {
const unpath = join(path + "/mods/", e.fileName);
const url = e.downloadUrl.replace("https://edge.forgecdn.net", this.utils.curseforge_Durl)
tmp.push([url, unpath])
// if (usemirror) {
// tmp.push([
// "https://mod.mcimirror.top" + new URL(e.downloadUrl).pathname,
// unpath,
// ]);
// } else {
// tmp.push([e.downloadUrl, unpath]);
// }
}
);
});
await Wfastdownload(tmp as unknown as [string, string],ws); //下载文件
await Wfastdownload(tmp,ws); //下载文件
}
}

View File

@@ -1,10 +1,10 @@
import { MessageWS } from "../utils/ws.js";
import { CurseForge } from "./curseforge.js";
import { Modrinth } from "./modrinth.js";
import { WebSocket } from "ws";
import { Modrinth } from "./modrinth.js";;
export interface XPlatform {
getinfo(manifest: object): Promise<modpack_info>;
downloadfile(manifest: object,path:string,ws:WebSocket): Promise<void>;
downloadfile(manifest: object,path:string,ws:MessageWS): Promise<void>;
}
export interface modpack_info {

View File

@@ -3,6 +3,7 @@ import { WebSocket } from "ws";
import { Wfastdownload, Utils } from "../utils/utils.js";
import { modpack_info, XPlatform } from "./index.js";
import { join } from "node:path";
import { MessageWS } from "../utils/ws.js";
interface ModrinthManifest {
files: Array<{ path: string; downloads: string[]; fileSize: number; }>;
@@ -35,7 +36,7 @@ export class Modrinth implements XPlatform {
}
return result;
}
async downloadfile(manifest: object,path:string,ws:WebSocket): Promise<void> {
async downloadfile(manifest: object,path:string,ws:MessageWS): Promise<void> {
const index = manifest as ModrinthManifest;
let tmp: [string, string][] = []
index.files.forEach(async (e: { path: string; downloads: string[]; fileSize: number;}) => {
@@ -44,13 +45,8 @@ export class Modrinth implements XPlatform {
}
const url = e.downloads[0].replace("https://cdn.modrinth.com",this.utils.modrinth_Durl)
const unpath = join(path,e.path)
tmp.push([e.downloads[0],unpath])
// if (usemirror){
// tmp.push(["https://mod.mcimirror.top"+new URL(e.downloads[0]).pathname,unpath,String(e.fileSize)])
// }else{
// tmp.push([e.downloads[0],unpath,String(e.fileSize)])
// }
tmp.push([url,unpath])
});
await Wfastdownload(tmp as unknown as [string, string],ws)
await Wfastdownload(tmp,ws)
}
}

View File

@@ -1,7 +1,17 @@
const env = process.env.DEBUG;
export function debug(msg: string){
export function debug(msg: any){
if (env === "true"){
console.info(msg);
if(msg instanceof Error){
console.log(`[ERROR] [${new Date().toLocaleString()}] `);
console.log(msg);
}
if (typeof msg === "string"){
console.log(`[DEBUG] [${new Date().toLocaleString()}] ` + msg);
}
if (typeof msg === "object"){
console.log(`[OBJ] [${new Date().toLocaleString()}] `);
console.log(msg);
}
}
}

View File

@@ -6,6 +6,7 @@ import fs from "node:fs";
import fse from "fs-extra";
import { WebSocket } from "ws";
import { ExecOptions, exec} from "node:child_process";
import { MessageWS } from "./ws.js";
export class Utils {
public modrinth_url: string;
@@ -62,30 +63,20 @@ export function execPromise(cmd:string,options?:ExecOptions){
})
}
export async function fastdownload(data: [string, string]) {
export async function fastdownload(data: [string, string]|string[][]) {
let _data = undefined;
if(Array.isArray(data[0])){
_data = data
}else{
_data = [data]
}
return await pMap(
[data],
_data,
async (e:any) => {
try {
await pRetry(
async () => {
if (!fs.existsSync(e[1])) {
/*
const size: number = await (async () => {
const head = (
await got.head(
e[0],
{ headers: { "user-agent": "DeEarthX" } }
)
).headers["content-length"];
if (head) {
return Number(head);
} else {
return 0;
}
})();*/
//console.log(e)
await got
.get(e[0], {
responseType: "buffer",
@@ -93,9 +84,6 @@ export async function fastdownload(data: [string, string]) {
"user-agent": "DeEarthX",
},
})
.on("downloadProgress", (progress) => {
//bar.update(progress.transferred);
})
.then((res) => {
fse.outputFileSync(e[1], res.rawBody);
});
@@ -111,7 +99,7 @@ export async function fastdownload(data: [string, string]) {
);
}
export async function Wfastdownload(data: [string, string],ws:WebSocket) {
export async function Wfastdownload(data: string[][],ws:MessageWS) {
let index = 1;
return await pMap(
data,
@@ -131,14 +119,15 @@ export async function Wfastdownload(data: [string, string],ws:WebSocket) {
fse.outputFileSync(e[1], res.rawBody);
});
}
ws.send(JSON.stringify({
status:"downloading",
result:{
total:data.length,
index:index,
name:e[1]
}
}))
ws.download(data.length,index,e[1])
// ws.send(JSON.stringify({
// status:"downloading",
// result:{
// total:data.length,
// index:index,
// name:e[1]
// }
// }))
index++
},
{ retries: 3 }
@@ -149,87 +138,4 @@ export async function Wfastdownload(data: [string, string],ws:WebSocket) {
},
{ concurrency: 16 }
);
}
export async function xfastdownload(data: [string, string][]) {
return await pMap(
data,
async (e:any) => {
try {
await pRetry(
async () => {
if (!fs.existsSync(e[1])) {
/*
const size: number = await (async () => {
const head = (
await got.head(
e[0],
{ headers: { "user-agent": "DeEarthX" } }
)
).headers["content-length"];
if (head) {
return Number(head);
} else {
return 0;
}
})();*/
//console.log(e)
await got
.get(e[0], {
responseType: "buffer",
headers: {
"user-agent": "DeEarthX",
},
})
.on("downloadProgress", (progress) => {
//bar.update(progress.transferred);
})
.then((res) => {
fse.outputFileSync(e[1], res.rawBody);
});
}
},
{ retries: 3 }
);
} catch (e) {
//LOGGER.error({ err: e });
}
},
{ concurrency: 16 }
);
}
export async function mr_fastdownload(data: [string, string, string]) {
return await pMap(
data,
async (e) => {
//const bar = multibar.create(Number(e[2]), 0, { filename: e[1] });
try {
await pRetry(
async () => {
if (!fse.existsSync(e[1])) {
await got
.get(e[0], {
responseType: "buffer",
headers: {
"user-agent": "DeEarthX",
},
})
.on("downloadProgress", (progress) => {
//bar.update(progress.transferred);
})
.then((res) => {
fse.outputFileSync(e[1], res.rawBody);
});
}
},
{ retries: 3 }
);
} catch (e) {
//LOGGER.error({ err: e });
}
},
{ concurrency: 16 }
);
}
}

56
backend/src/utils/ws.ts Normal file
View File

@@ -0,0 +1,56 @@
import websocket, { WebSocketServer } from "ws";
export class MessageWS {
ws!: websocket;
constructor(ws: websocket) {
this.ws = ws;
}
finish(first: number, latest: number) {
this.ws.send(
JSON.stringify({
status: "finish",
result: latest - first,
})
);
}
unzip(entryName: string, total: number, current: number) {
this.ws.send(
JSON.stringify({
status: "unzip",
result: { name: entryName, total, current },
})
);
}
download(total: number, index: number, name: string) {
this.ws.send(
JSON.stringify({
status: "downloading",
result: {
total,
index,
name,
},
})
);
}
statusChange() {
this.ws.send(
JSON.stringify({
status: "changed",
result: undefined,
})
);
}
handleError(error: Error) {
this.ws.send(
JSON.stringify({
status: "error",
result: error.message,
})
);
}
}