feat:大部分功能完成

This commit is contained in:
Tianpao
2025-09-28 00:21:01 +08:00
parent b359fc881e
commit 5f16ee2bfa
22 changed files with 471 additions and 121 deletions

View File

@@ -1,8 +1,11 @@
import fs from "node:fs";
import websocket from "ws";
import websocket, { WebSocketServer } from "ws";
import { yauzl_promise } from "./utils/yauzl.promise.js";
import { pipeline } from "node:stream/promises";
import { platform, what_platform } from "./platform/index.js";
import { DeEarth } from "./utils/DeEarth.js";
import { mlsetup } from "./modloader/index.js";
import { console } from "node:inspector";
interface Iinfo{
name:string
@@ -10,23 +13,45 @@ interface Iinfo{
}
export class Dex {
ws: websocket;
wsx!: WebSocketServer;
in: any;
constructor(ws: websocket) {
this.ws = ws;
ws!: websocket;
constructor(ws: WebSocketServer) {
this.wsx = ws;
this.wsx.on('connection',(e)=>{
this.ws = e
})
this.in = {}
console.log(this.ws)
}
public async Main(buffer: Buffer) {
const first = new Date().getTime()
const info = await this._getinfo(buffer)
const plat = what_platform(info)
const mpname = this.in.name
const unpath = `./instance/${mpname}`
await Promise.all([
this._unzip(buffer,mpname),
platform(plat).downloadfile(this.in,`./instance/${mpname}`)
])
this.ws.send(JSON.stringify({ status: "changed", result: undefined })); //改变状态
await platform(plat).downloadfile(this.in,unpath,this.ws)
]) // 解压和下载
this.ws.send(JSON.stringify({
status: "changed",
result: undefined
})); //改变状态
await new DeEarth(`${unpath}/mods`,`./.rubbish/${mpname}`).Main()
this.ws.send(JSON.stringify({
status: "changed",
result: undefined
})); //改变状态(DeEarth筛选模组完毕)
const mlinfo = await platform(plat).getinfo(this.in)
await mlsetup(mlinfo.loader,mlinfo.minecraft,mlinfo.loader_version,unpath) //安装服务端
const latest = new Date().getTime()
console.log(latest - first)
this.ws.send(JSON.stringify({
status: "finish",
result: latest - first
}))
//await this._unzip(buffer);
}
@@ -34,9 +59,12 @@ export class Dex {
const important_name = ["manifest.json","modrinth.index.json"]
let contain:string = ""
const zip = await yauzl_promise(buffer);
zip.filter(e=>important_name.includes(e.fileName)).forEach(async e=>{
this.in = JSON.parse((await e.ReadEntry).toString())
zip.forEach(async e=>{
if (important_name.includes(e.fileName)){
contain = e.fileName
this.in = JSON.parse((e.ReadEntrySync).toString())
return;
}
})
return contain;
}
@@ -44,7 +72,7 @@ export class Dex {
private async _unzip(buffer: Buffer,instancename:string) {
/* 解压Zip */
const zip = await yauzl_promise(buffer);
let index = 0;
let index = 1;
for await (const entry of zip) {
const ew = entry.fileName.endsWith("/");
if (ew) {
@@ -56,10 +84,10 @@ export class Dex {
const dirPath = `./instance/${instancename}/${entry.fileName.substring(
0,
entry.fileName.lastIndexOf("/")
)}`;
).replace("overrides/","")}`;
await fs.promises.mkdir(dirPath, { recursive: true });
const stream = await entry.openReadStream;
const write = fs.createWriteStream(`./instance/${instancename}/${entry.fileName}`);
const write = fs.createWriteStream(`./instance/${instancename}/${entry.fileName.replace("overrides/","")}`);
await pipeline(stream, write);
}
this.ws.send(JSON.stringify({ status: "unzip", result: { name: entry.fileName,total: zip.length, current:index } }));

View File

@@ -7,25 +7,27 @@ import fs from "node:fs"
import { pipeline } from "node:stream/promises";
import { Config, IConfig } from "./utils/config.js";
import { yauzl_promise } from "./utils/yauzl.promise.js";
import { Dex } from "./Dex.js";
import { mlsetup } from "./modloader/index.js";
export class Core {
private config: IConfig;
private readonly app: Application;
private readonly server: Server;
public ws!: websocket;
public ws!: WebSocketServer;
private wsx!: websocket;
private readonly upload: multer.Multer;
private task: {} = {};
dex: Dex;
constructor(config: IConfig) {
this.config = config
this.app = express();
this.upload = multer()
this.server = createServer(this.app);
new WebSocketServer({ server: this.server }).on("connection", (ws) => {
this.ws = ws;
this.upload = multer()
this.ws = new WebSocketServer({ server: this.server })
this.ws.on("connection",(e)=>{
this.wsx = e
})
}
async DeEarthX(buffer:Buffer){
this.dex = new Dex(this.ws)
}
express() {
@@ -35,7 +37,8 @@ export class Core {
if (!req.file) {
return;
}
this.DeEarthX(req.file.buffer)
this.dex.Main(req.file.buffer) //Dex
//this.dex.Main(req.file.buffer)
res.json({
status:200,
message:"task is peding"

View File

@@ -9,6 +9,7 @@ import { version_compare } from "./utils/utils.js";
import { Forge } from "./modloader/forge.js";
import { Minecraft } from "./modloader/minecraft.js";
import { Fabric } from "./modloader/fabric.js";
import { NeoForge } from "./modloader/neoforge.js";
const core = new Core(config);
@@ -21,7 +22,8 @@ core.start();
// async function Dex(buffer: Buffer) {
// }
// new Forge("1.20.1","47.3.10").setup()
//new Forge("1.20.1","47.3.10").setup()
//await new NeoForge("1.21.1","21.1.1").setup()
//await new Minecraft("forge","1.20.1","0").setup()
// await new Minecraft("forge","1.16.5","0").setup()
await new Fabric("1.20.1","0.17.2").setup()
//await new Fabric("1.20.1","0.17.2").setup()

View File

@@ -1,5 +1,6 @@
import got, { Got } from "got";
import { fastdownload, xfastdownload } from "../utils/utils.js";
import fs from "node:fs"
import { execPromise, fastdownload, xfastdownload } from "../utils/utils.js";
interface ILatestLoader{
url:string,
@@ -16,9 +17,11 @@ export class Fabric{
minecraft: string;
loaderVersion: string;
got:Got
constructor(minecraft:string,loaderVersion:string) {
path: string;
constructor(minecraft:string,loaderVersion:string,path:string) {
this.minecraft = minecraft;
this.loaderVersion = loaderVersion;
this.path = path
this.got = got.extend({
prefixUrl:"https://bmclapi2.bangbang93.com/",
headers:{
@@ -27,16 +30,31 @@ export class Fabric{
})
}
async setup(){
async setup():Promise<void>{
await this.getLaestLoader()
await this.libraries()
await this.install()
await this.wshell()
}
async install(){
await execPromise(`java -jar fabric-installer.jar server -dir . -mcversion ${this.minecraft} -loader ${this.loaderVersion}`,{
cwd:this.path
})
}
private async wshell(){
const cmd = `java -jar fabric-server-launch.jar`
await fs.promises.writeFile(`${this.path}/run.bat`,`@echo off\n${cmd}`) //Windows
await fs.promises.writeFile(`${this.path}/run.sh`,`#!/bin/bash\n${cmd}`) //Linux
}
async libraries(){
const res = await this.got.get(`fabric-meta/v2/versions/loader/${this.minecraft}/${this.loaderVersion}/server/json`).json<IServer>()
const _downlist: [string,string][]= []
res.libraries.forEach(e=>{
const path = this.MTP(e.name)
_downlist.push([`https://bmclapi2.bangbang93.com/maven/${path}`,`./fabric/libraries/${path}`])
_downlist.push([`https://bmclapi2.bangbang93.com/maven/${path}`,`${this.path}/libraries/${path}`])
})
await xfastdownload(_downlist)
}
@@ -46,11 +64,12 @@ export class Fabric{
const res = await this.got.get("fabric-meta/v2/versions/installer").json<ILatestLoader[]>()
res.forEach(e=>{
if(e.stable){
downurl = `https://bmclapi2.bangbang93.com/maven/${new URL(e.url).pathname.slice(1)}`
//downurl = `https://bmclapi2.bangbang93.com/maven/${new URL(e.url).pathname.slice(1)}`
downurl = e.url
return;
}
})
await fastdownload([downurl,`./fabric/fabric-installer.jar`])
await fastdownload([downurl,`${this.path}/fabric-installer.jar`])
}
private MTP(string:string){

View File

@@ -1,8 +1,9 @@
import got, { Got } from "got";
import fs from "node:fs"
import fse from "fs-extra"
import { version_compare, xfastdownload } from "../utils/utils.js";
import { execPromise, fastdownload, version_compare, xfastdownload } from "../utils/utils.js";
import { yauzl_promise } from "../utils/yauzl.promise.js";
import { execSync } from "node:child_process";
interface Iforge{
data:{
@@ -27,9 +28,11 @@ export class Forge {
minecraft: string;
loaderVersion: string;
got: Got;
constructor(minecraft:string,loaderVersion:string){
path: string;
constructor(minecraft:string,loaderVersion:string,path:string){
this.minecraft = minecraft;
this.loaderVersion = loaderVersion;
this.path = path
this.got = got.extend({
prefixUrl: "https://bmclapi2.bangbang93.com",
headers: { "User-Agent": "DeEarthX" },
@@ -39,6 +42,7 @@ export class Forge {
async setup(){
await this.installer()
await this.library()
await this.install()
if (version_compare(this.minecraft,"1.18") === -1){
await this.wshell()
}
@@ -46,13 +50,13 @@ export class Forge {
async library(){
const _downlist: [string,string][]= []
const data = await fs.promises.readFile(`./forge/forge-${this.minecraft}-${this.loaderVersion}-installer.jar`)
const data = await fs.promises.readFile(`${this.path}/forge-${this.minecraft}-${this.loaderVersion}-installer.jar`)
const zip = await yauzl_promise(data)
for await(const entry of zip){
if(entry.fileName === "version.json" || entry.fileName === "install_profile.json"){ //Libraries
JSON.parse((await entry.ReadEntry).toString()).libraries.forEach(async (e:any)=>{
const t = e.downloads.artifact.path
_downlist.push([`https://bmclapi2.bangbang93.com/maven/${t}`,`./forge/libraries/${t}`])
_downlist.push([`https://bmclapi2.bangbang93.com/maven/${t}`,`${this.path}/libraries/${t}`])
})
}
if(entry.fileName === "install_profile.json"){ //MOJMAPS
@@ -61,13 +65,13 @@ export class Forge {
const vjson = await this.got.get(`version/${this.minecraft}/json`).json<Iversion>()
console.log(`${new URL(vjson.downloads.server_mappings.url).pathname}`)
const mojpath = this.MTP(json.data.MOJMAPS.server)
_downlist.push([`https://bmclapi2.bangbang93.com/${new URL(vjson.downloads.server_mappings.url).pathname.slice(1)}`,`./forge/libraries/${mojpath}`])
_downlist.push([`https://bmclapi2.bangbang93.com/${new URL(vjson.downloads.server_mappings.url).pathname.slice(1)}`,`${this.path}/libraries/${mojpath}`])
/* 获取MOJMAPS */
/*获取MAPPING*/
const mappingobj = json.data.MAPPINGS.server
const path = this.MTP(mappingobj.replace(":mappings@txt","@zip"))
_downlist.push([`https://bmclapi2.bangbang93.com/maven/${path}`,`./forge/libraries/${path}`])
_downlist.push([`https://bmclapi2.bangbang93.com/maven/${path}`,`${this.path}/libraries/${path}`])
/* 获取MAPPING */
}
}
@@ -75,15 +79,19 @@ export class Forge {
await xfastdownload(downlist)
}
async install(){
await execPromise(`java -jar forge-${this.minecraft}-${this.loaderVersion}-installer.jar --installServer`,{cwd:this.path})
}
async installer(){
const res = (await this.got.get(`forge/download?mcversion=${this.minecraft}&version=${this.loaderVersion}&category=installer&format=jar`)).rawBody;
await fse.outputFile(`./forge/forge-${this.minecraft}-${this.loaderVersion}-installer.jar`,res);
await fse.outputFile(`${this.path}/forge-${this.minecraft}-${this.loaderVersion}-installer.jar`,res);
}
private async wshell(){
const cmd = `java -jar forge-${this.minecraft}-${this.loaderVersion}.jar`
await fs.promises.writeFile("./forge/run.bat",`@echo off\n${cmd}`) //Windows
await fs.promises.writeFile("./forge/run.sh",`#!/bin/bash\n${cmd}`) //Linux
await fs.promises.writeFile(`${this.path}/run.bat`,`@echo off\n${cmd}`) //Windows
await fs.promises.writeFile(`${this.path}/run.sh`,`#!/bin/bash\n${cmd}`) //Linux
}
private MTP(string:string){

View File

@@ -1,15 +1,36 @@
import { Fabric } from "./fabric.js";
import { Forge } from "./forge.js";
import { Minecraft } from "./minecraft.js";
import { NeoForge } from "./neoforge.js";
interface XModloader {
setup: Promise<void>
setup(): Promise<void>
}
export function modloader(ml:string,mcv:string,mlv:string){
export function modloader(ml:string,mcv:string,mlv:string,path:string){
let modloader:XModloader
switch (ml) {
case "fabric":
modloader = new Fabric(mcv,mlv,path)
break;
case "fabric-loader":
modloader = new Fabric(mcv,mlv,path)
break;
case "forge":
modloader = new Forge(mcv,mlv,path)
break;
case "neoforge":
modloader = new NeoForge(mcv,mlv,path)
break;
default:
modloader = new Minecraft(ml,mcv,mlv,path)
break;
}
return modloader
}
export async function mlsetup(ml:string,mcv:string,mlv:string,path:string){
const minecraft = new Minecraft(ml,mcv,mlv,path);
console.log(ml)
await modloader(ml,mcv,mlv,path).setup()
await minecraft.setup()
}

View File

@@ -1,72 +1,120 @@
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:{
downloads:{
artifact:{
path:string
interface ILInfo {
libraries: {
downloads: {
artifact: {
path: string
}
}
}[]
}
export class Minecraft{
export class Minecraft {
loader: string;
minecraft: string;
loaderVersion: string;
constructor(loader:string,minecraft:string,lv:string){
path: string;
constructor(loader: string, minecraft: string, lv: string,path:string) {
this.path = path
this.loader = loader;
this.minecraft = minecraft;
this.loaderVersion = lv;
}
async setup(){
switch (this.loader){
case "forge":
await this.forge_setup();
break;
}
async setup() {
switch (this.loader) {
case "forge":
await this.forge_setup();
break;
case "neoforge":
await this.forge_setup();
break;
case "fabric":
await this.fabric_setup();
break;
case "fabric-loader":
await this.fabric_setup();
break;
}
await this.eula() //生成Eula.txt
}
async forge_setup(){
if(version_compare(this.minecraft,"1.18") === 1){
// 1.18.x + MC依赖解压
const mcpath = `./forge/libraries/net/minecraft/server/${this.minecraft}/server-${this.minecraft}.jar`
await fastdownload([`https://bmclapi2.bangbang93.com/version/${this.minecraft}/server`,mcpath])
const zip = await yauzl_promise(await fs.promises.readFile(mcpath))
for await(const entry of zip){
if(entry.fileName.startsWith("META-INF/libraries/")&&!entry.fileName.endsWith("/")){
console.log(entry.fileName)
const stream = await entry.openReadStream;
const write = fs.createWriteStream(`./forge/libraries/${entry.fileName.replace("META-INF/libraries/","")}`);
await pipeline(stream, write);
}
}
// 1.18.x + 依赖解压
}else{
//1.18.x - MC依赖下载
const lowv = `./forge/minecraft_server.${this.minecraft}.jar`
const dmc = fastdownload([`https://bmclapi2.bangbang93.com/version/${this.minecraft}/server`,lowv])
const download:Promise<void> = new Promise(async (resolve)=>{
console.log("并行")
const json = await got.get(`https://bmclapi2.bangbang93.com/version/${this.minecraft}/json`,{
headers:{
"User-Agent": "DeEarthX"
async forge_setup() {
if (version_compare(this.minecraft, "1.18") === 1) {
// 1.18.x + MC依赖解压
const mcpath = `${this.path}/libraries/net/minecraft/server/${this.minecraft}/server-${this.minecraft}.jar`
await fastdownload([`https://bmclapi2.bangbang93.com/version/${this.minecraft}/server`, mcpath])
const zip = await yauzl_promise(await fs.promises.readFile(mcpath))
for await (const entry of zip) {
if (entry.fileName.startsWith("META-INF/libraries/") && !entry.fileName.endsWith("/")) {
console.log(entry.fileName)
const stream = await entry.openReadStream;
const write = fs.createWriteStream(`${this.path}/libraries/${entry.fileName.replace("META-INF/libraries/", "")}`);
await pipeline(stream, write);
}
}
// 1.18.x + 依赖解压
} else {
//1.18.x - MC依赖下载
const lowv = `${this.path}/minecraft_server.${this.minecraft}.jar`
const dmc = fastdownload([`https://bmclapi2.bangbang93.com/version/${this.minecraft}/server`, lowv])
const download: Promise<void> = new Promise(async (resolve) => {
console.log("并行")
const json = await got.get(`https://bmclapi2.bangbang93.com/version/${this.minecraft}/json`, {
headers: {
"User-Agent": "DeEarthX"
}
})
.json<ILInfo>()
json.libraries.forEach(async e => {
const path = e.downloads.artifact.path
await fastdownload([`https://bmclapi2.bangbang93.com/maven/${path}`, `${this.path}/libraries/${path}`])
})
resolve()
})
.json<ILInfo>()
json.libraries.forEach(async e=>{
const path = e.downloads.artifact.path
await fastdownload([`https://bmclapi2.bangbang93.com/maven/${path}`,`./forge/libraries/${path}`])
})
resolve()
})
await Promise.all([dmc,download])
//1.18.x - 依赖下载
await Promise.all([dmc, download])
//1.18.x - 依赖下载
}
}
async fabric_setup() {
const mcpath = `${this.path}/server.jar`
await fastdownload([`https://bmclapi2.bangbang93.com/version/${this.minecraft}/server`, mcpath])
// 依赖解压
const zip = await yauzl_promise(await fs.promises.readFile(mcpath))
for await (const entry of zip) {
// if (entry.fileName.startsWith("META-INF/libraries/") && entry.fileName.endsWith("/") &&entry.fileName !== "META-INF/libraries/") {
// fs.promises.mkdir(`${this.path}/libraries/${entry.fileName.replace("META-INF/libraries/", "")}`,{
// recursive:true
// })
// }
if (entry.fileName.startsWith("META-INF/libraries/") && !entry.fileName.endsWith("/")) {
// const stream = await entry.openReadStream;
// fs.promises.mkdir(pa.dirname(`${this.path}/libraries/${entry.fileName.replace("META-INF/libraries/", "")}`),{
// recursive:true
// })
// const write = fs.createWriteStream(`${this.path}/libraries/${entry.fileName.replace("META-INF/libraries/", "")}`);
// await pipeline(stream, write);
const out = entry.ReadEntrySync
await fsExtra.outputFile(`${this.path}/libraries/${entry.fileName.replace("META-INF/libraries/", "")}`,out)
}
}
// 依赖解压
}
async eula(){
const context = `
#By changing the setting below to TRUE you are indicating your agreement to our EULA (https://aka.ms/MinecraftEULA).
#Spawn by DeEarthX(QQgroup:559349662) Tianpao:(https://space.bilibili.com/1728953419)
eula=true
`
await fs.promises.writeFile(`${this.path}/eula.txt`,context)
}
}

View File

@@ -1,18 +1,19 @@
import fse from "fs-extra"
import { Forge } from "./forge.js";
class NeoForge extends Forge{
constructor(minecraft:string,loaderVersion:string){
super(minecraft,loaderVersion); //子承父业
export class NeoForge extends Forge{
constructor(minecraft:string,loaderVersion:string,path:string){
super(minecraft,loaderVersion,path); //子承父业
}
async setup(){
await this.installer();
await this.library();
await this.install();
}
async installer(){
const res = (await this.got.get(`neoforge/version/${this.loaderVersion}/download/installer.jar`)).rawBody;
await fse.outputFile(`./forge/forge-${this.minecraft}-${this.loaderVersion}-installer.jar`,res);
await fse.outputFile(`${this.path}/forge-${this.minecraft}-${this.loaderVersion}-installer.jar`,res);
}
}

View File

@@ -1,6 +1,7 @@
import got from "got";
import { WebSocket } from "ws";
import { join } from "node:path";
import { fastdownload, Utils } from "../utils/utils.js";
import { Wfastdownload, Utils } from "../utils/utils.js";
import { modpack_info, XPlatform } from "./index.js";
export interface CurseForgeManifest {
@@ -28,7 +29,7 @@ export class CurseForge implements XPlatform {
return result;
}
async downloadfile(manifest: object, path: string): Promise<void> {
async downloadfile(manifest: object, path: string, ws:WebSocket): Promise<void> {
const local_manifest = manifest as CurseForgeManifest;
if (local_manifest.files.length === 0){
return;
@@ -70,6 +71,6 @@ export class CurseForge implements XPlatform {
}
);
});
await fastdownload(tmp as unknown as [string, string]); //下载文件
await Wfastdownload(tmp as unknown as [string, string],ws); //下载文件
}
}

View File

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

View File

@@ -1,5 +1,6 @@
import fs from "node:fs";
import { mr_fastdownload, Utils } from "../utils/utils.js";
import { WebSocket } from "ws";
import { Wfastdownload, Utils } from "../utils/utils.js";
import { modpack_info, XPlatform } from "./index.js";
import { join } from "node:path";
@@ -34,22 +35,22 @@ export class Modrinth implements XPlatform {
}
return result;
}
async downloadfile(manifest: object,path:string): Promise<void> {
async downloadfile(manifest: object,path:string,ws:WebSocket): Promise<void> {
const index = manifest as ModrinthManifest;
let tmp: [string, string, string][] = []
let tmp: [string, string][] = []
index.files.forEach(async (e: { path: string; downloads: string[]; fileSize: number;}) => {
if (e.path.endsWith(".zip")) {
return;
}
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,String(e.fileSize)])
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)])
// }
});
await mr_fastdownload(tmp as unknown as [string, string, string])
await Wfastdownload(tmp as unknown as [string, string],ws)
}
}

View File

@@ -3,6 +3,8 @@ import crypto from "node:crypto"
import { yauzl_promise } from "./yauzl.promise.js"
import got from "got"
import { Utils } from "./utils.js"
import pa from "node:path"
import WebSocket from "ws"
interface IMixins{
name: string
data: string
@@ -29,9 +31,9 @@ export class DeEarth{
modspath: string
file: IFile[]
utils: Utils
constructor(modspath:string) {
constructor(modspath:string,movepath:string) {
this.utils = new Utils();
this.movepath = "./.rubbish"
this.movepath = movepath
this.modspath = modspath
this.file = []
}
@@ -44,8 +46,10 @@ export class DeEarth{
const hash = await this.Check_Hashes()
const mixins = await this.Check_Mixins()
const result = [...new Set(hash.concat(mixins))]
console.log(result)
result.forEach(async e=>{
await fs.promises.rename(`${this.modspath}/${e}`,`${this.movepath}/${e}`)
await fs.promises.rename(`${e}`,`${this.movepath}/${e}`.replace(this.modspath,""))
//await fs.promises.rename(`${this.modspath}/${e}`,`${this.movepath}/${e}`)
})
}

View File

@@ -4,6 +4,8 @@ import got from "got";
import pRetry from "p-retry";
import fs from "node:fs";
import fse from "fs-extra";
import { WebSocket } from "ws";
import { ExecOptions, exec} from "node:child_process";
export class Utils {
public modrinth_url: string;
@@ -47,6 +49,19 @@ export function version_compare(v1: string, v2: string) {
return 0;
}
export function execPromise(cmd:string,options:ExecOptions){
return new Promise((resolve,reject)=>{
exec(cmd,options,(err,stdout,stderr)=>{
if(err){
reject(err)
return;
}
}).on('exit',(code)=>{
resolve(code)
})
})
}
export async function fastdownload(data: [string, string]) {
return await pMap(
[data],
@@ -95,6 +110,46 @@ export async function fastdownload(data: [string, string]) {
);
}
export async function Wfastdownload(data: [string, string],ws:WebSocket) {
let index = 1;
return await pMap(
data,
async (e:any) => {
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);
});
}
ws.send(JSON.stringify({
status:"downloading",
result:{
total:data.length,
index:index,
name:e[1]
}
}))
index++
},
{ retries: 3 }
);
} catch (e) {
//LOGGER.error({ err: e });
}
},
{ concurrency: 16 }
);
}
export async function xfastdownload(data: [string, string][]) {
return await pMap(
data,

View File

@@ -4,6 +4,7 @@ import Stream from "node:stream"
export interface IentryP extends yauzl.Entry {
openReadStream: Promise<Stream.Readable>;
ReadEntry: Promise<Buffer>;
ReadEntrySync: Buffer;
}
export async function yauzl_promise(buffer: Buffer): Promise<IentryP[]>{
@@ -27,7 +28,8 @@ export async function yauzl_promise(buffer: Buffer): Promise<IentryP[]>{
isEncrypted: entry.isEncrypted,
isCompressed: entry.isCompressed,
openReadStream: _openReadStream(zip,entry),
ReadEntry: _ReadEntry(zip,entry)
ReadEntry: _ReadEntry(zip,entry),
ReadEntrySync: (await _ReadEntry(zip,entry))
}
entries.push(_entry)
if (zip.entryCount === entries.length){