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 fs from "node:fs";
import p from "node:path" import p from "node:path";
import websocket, { WebSocketServer } from "ws"; import websocket, { WebSocketServer } from "ws";
import { yauzl_promise } from "./utils/yauzl.promise.js"; import { yauzl_promise } from "./utils/yauzl.promise.js";
import { pipeline } from "node:stream/promises"; import { pipeline } from "node:stream/promises";
@@ -8,103 +8,95 @@ import { DeEarth } from "./utils/DeEarth.js";
import { dinstall, mlsetup } from "./modloader/index.js"; import { dinstall, mlsetup } from "./modloader/index.js";
import config from "./utils/config.js"; import config from "./utils/config.js";
import { execPromise } from "./utils/utils.js"; import { execPromise } from "./utils/utils.js";
import { MessageWS } from "./utils/ws.js";
import { debug } from "./utils/logger.js";
export class Dex { export class Dex {
wsx!: WebSocketServer; wsx!: WebSocketServer;
in: any; message!: MessageWS;
ws!: websocket;
constructor(ws: WebSocketServer) { constructor(ws: WebSocketServer) {
this.wsx = ws; this.wsx = ws;
this.wsx.on("connection", (e) => { this.wsx.on("connection", (e) => {
this.ws = e; this.message = new MessageWS(e);
}); });
this.in = {};
} }
public async Main(buffer: Buffer, dser: boolean) { public async Main(buffer: Buffer, dser: boolean) {
try{ try {
const first = Date.now(); const first = Date.now();
const info = await this._getinfo(buffer).catch((e)=>{ const { contain, info } = await this._getinfo(buffer).catch((e) => {
throw new Error(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)
}); });
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) { private async _getinfo(buffer: Buffer) {
const important_name = ["manifest.json", "modrinth.index.json"]; const important_name = ["manifest.json", "modrinth.index.json"];
let contain: string = ""; let contain: string = "";
let info: any = {};
const zip = await yauzl_promise(buffer); const zip = await yauzl_promise(buffer);
zip.forEach(async (e) => { for await (const entry of zip) {
if (important_name.includes(e.fileName)) { if (important_name.includes(entry.fileName)) {
contain = e.fileName; contain = entry.fileName;
this.in = JSON.parse((await e.ReadEntry).toString()); info = JSON.parse((await entry.ReadEntry).toString());
return; break;
} }
}); }
return contain; return { contain, info };
} }
private async _unzip(buffer: Buffer, instancename: string) { private async _unzip(buffer: Buffer, instancename: string) {
@@ -139,12 +131,13 @@ export class Dex {
); );
await pipeline(stream, write); await pipeline(stream, write);
} }
this.ws.send( this.message.unzip(entry.fileName, zip.length, index);
JSON.stringify({ // this.ws.send(
status: "unzip", // JSON.stringify({
result: { name: entry.fileName, total: zip.length, current: index }, // status: "unzip",
}) // result: { name: entry.fileName, total: zip.length, current: index },
); // })
// );
index++; index++;
} }
/* 解压完成 */ /* 解压完成 */

View File

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

View File

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

View File

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

View File

@@ -3,6 +3,7 @@ import { WebSocket } from "ws";
import { join } from "node:path"; import { join } from "node:path";
import { Wfastdownload, Utils } from "../utils/utils.js"; import { Wfastdownload, Utils } from "../utils/utils.js";
import { modpack_info, XPlatform } from "./index.js"; import { modpack_info, XPlatform } from "./index.js";
import { MessageWS } from "../utils/ws.js";
export interface CurseForgeManifest { export interface CurseForgeManifest {
minecraft: { minecraft: {
@@ -39,7 +40,7 @@ export class CurseForge implements XPlatform {
return result; 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; const local_manifest = manifest as CurseForgeManifest;
if (local_manifest.files.length === 0){ if (local_manifest.files.length === 0){
return; return;
@@ -49,7 +50,7 @@ export class CurseForge implements XPlatform {
(file: { fileID: number }) => file.fileID (file: { fileID: number }) => file.fileID
), ),
}); });
let tmp: [string, string] | string[][] = []; let tmp: string[][] = [];
await this.got await this.got
.post("v1/mods/files", { .post("v1/mods/files", {
body: FileID, body: FileID,
@@ -64,17 +65,9 @@ export class CurseForge implements XPlatform {
const unpath = join(path + "/mods/", e.fileName); const unpath = join(path + "/mods/", e.fileName);
const url = e.downloadUrl.replace("https://edge.forgecdn.net", this.utils.curseforge_Durl) const url = e.downloadUrl.replace("https://edge.forgecdn.net", this.utils.curseforge_Durl)
tmp.push([url, unpath]) 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 { CurseForge } from "./curseforge.js";
import { Modrinth } from "./modrinth.js"; import { Modrinth } from "./modrinth.js";;
import { WebSocket } from "ws";
export interface XPlatform { export interface XPlatform {
getinfo(manifest: object): Promise<modpack_info>; 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 { export interface modpack_info {

View File

@@ -3,6 +3,7 @@ import { WebSocket } from "ws";
import { Wfastdownload, Utils } from "../utils/utils.js"; import { Wfastdownload, Utils } from "../utils/utils.js";
import { modpack_info, XPlatform } from "./index.js"; import { modpack_info, XPlatform } from "./index.js";
import { join } from "node:path"; import { join } from "node:path";
import { MessageWS } from "../utils/ws.js";
interface ModrinthManifest { interface ModrinthManifest {
files: Array<{ path: string; downloads: string[]; fileSize: number; }>; files: Array<{ path: string; downloads: string[]; fileSize: number; }>;
@@ -35,7 +36,7 @@ export class Modrinth implements XPlatform {
} }
return result; 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; const index = manifest as ModrinthManifest;
let tmp: [string, string][] = [] let tmp: [string, string][] = []
index.files.forEach(async (e: { path: string; downloads: string[]; fileSize: number;}) => { 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 url = e.downloads[0].replace("https://cdn.modrinth.com",this.utils.modrinth_Durl)
const unpath = join(path,e.path) const unpath = join(path,e.path)
tmp.push([e.downloads[0],unpath]) tmp.push([url,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)])
// }
}); });
await Wfastdownload(tmp as unknown as [string, string],ws) await Wfastdownload(tmp,ws)
} }
} }

View File

@@ -1,7 +1,17 @@
const env = process.env.DEBUG; const env = process.env.DEBUG;
export function debug(msg: string){ export function debug(msg: any){
if (env === "true"){ 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 fse from "fs-extra";
import { WebSocket } from "ws"; import { WebSocket } from "ws";
import { ExecOptions, exec} from "node:child_process"; import { ExecOptions, exec} from "node:child_process";
import { MessageWS } from "./ws.js";
export class Utils { export class Utils {
public modrinth_url: string; 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( return await pMap(
[data], _data,
async (e:any) => { async (e:any) => {
try { try {
await pRetry( await pRetry(
async () => { async () => {
if (!fs.existsSync(e[1])) { 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 await got
.get(e[0], { .get(e[0], {
responseType: "buffer", responseType: "buffer",
@@ -93,9 +84,6 @@ export async function fastdownload(data: [string, string]) {
"user-agent": "DeEarthX", "user-agent": "DeEarthX",
}, },
}) })
.on("downloadProgress", (progress) => {
//bar.update(progress.transferred);
})
.then((res) => { .then((res) => {
fse.outputFileSync(e[1], res.rawBody); 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; let index = 1;
return await pMap( return await pMap(
data, data,
@@ -131,14 +119,15 @@ export async function Wfastdownload(data: [string, string],ws:WebSocket) {
fse.outputFileSync(e[1], res.rawBody); fse.outputFileSync(e[1], res.rawBody);
}); });
} }
ws.send(JSON.stringify({ ws.download(data.length,index,e[1])
status:"downloading", // ws.send(JSON.stringify({
result:{ // status:"downloading",
total:data.length, // result:{
index:index, // total:data.length,
name:e[1] // index:index,
} // name:e[1]
})) // }
// }))
index++ index++
}, },
{ retries: 3 } { retries: 3 }
@@ -150,86 +139,3 @@ export async function Wfastdownload(data: [string, string],ws:WebSocket) {
{ concurrency: 16 } { 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,
})
);
}
}

View File

@@ -133,7 +133,7 @@ function prews(){
if (_data.status === "error"){ if (_data.status === "error"){
notification.error({ notification.error({
message: "DeEarth.X.Core 遇到了一个致命错误!", message: "DeEarth.X.Core 遇到了一个致命错误!",
description:_data.result description:`请将整个窗口截图发在群里\n错误信息${_data.result}`
}) })
} }
}) })