chore:人工修改屎山
This commit is contained in:
@@ -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++;
|
||||
}
|
||||
/* 解压完成 */
|
||||
|
||||
@@ -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(){
|
||||
|
||||
@@ -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(){
|
||||
|
||||
@@ -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: {
|
||||
|
||||
@@ -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); //下载文件
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
56
backend/src/utils/ws.ts
Normal 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,
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user