feat:UI及部分后端
This commit is contained in:
1229
backend/package-lock.json
generated
1229
backend/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -7,15 +7,26 @@
|
||||
"type": "module",
|
||||
"main": "main.js",
|
||||
"scripts": {
|
||||
"test": "node main.js"
|
||||
"test": "tsc&&node dist/main.js",
|
||||
"rollup": "rollup -c rollup.config.js",
|
||||
"nexe": "nexe -i ./dist/bundle.js --ico Dex.ico --build -t x86-22.13.0 --output ./dist/Dex-v3-core.exe",
|
||||
"build": "npm run rollup && npm run nexe"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@rollup/plugin-commonjs": "^28.0.6",
|
||||
"@rollup/plugin-json": "^6.1.0",
|
||||
"@rollup/plugin-node-resolve": "^16.0.1",
|
||||
"@rollup/plugin-typescript": "^12.1.4",
|
||||
"nexe": "^5.0.0-beta.4",
|
||||
"rollup": "^4.50.1",
|
||||
"typescript": "^5.9.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"fs-extra": "^11.3.1",
|
||||
"got": "^14.4.8",
|
||||
"p-map": "^7.0.3"
|
||||
"inquirer": "^12.9.4",
|
||||
"p-map": "^7.0.3",
|
||||
"picocolors": "^1.1.1",
|
||||
"yauzl-promise": "^4.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
16
backend/src/main.ts
Normal file
16
backend/src/main.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import config,{ Config } from "./utils/config.js";
|
||||
|
||||
const input = process.argv[2];
|
||||
|
||||
switch (input) {
|
||||
case 'getconfig': //读取配置
|
||||
process.stdout.write(JSON.stringify(config));
|
||||
break;
|
||||
case 'writeconfig': //写入配置
|
||||
if(process.argv.length < 4){
|
||||
process.exit(1);
|
||||
}
|
||||
Config.write_config(JSON.parse(process.argv[3]));
|
||||
break;
|
||||
case 'start':
|
||||
}
|
||||
73
backend/src/platform/curseforge.ts
Normal file
73
backend/src/platform/curseforge.ts
Normal file
@@ -0,0 +1,73 @@
|
||||
import got from "got";
|
||||
import { join } from "node:path";
|
||||
import { fastdownload, usemirror } from "../utils/utils.js";
|
||||
import { modpack_info, XPlatform } from "./index.js";
|
||||
|
||||
const cf_url = (() => {
|
||||
if (usemirror) {
|
||||
return "https://mod.mcimirror.top/curseforge";
|
||||
} else {
|
||||
return "https://api.curseforge.com";
|
||||
}
|
||||
})();
|
||||
export interface CurseForgeManifest {
|
||||
minecraft: {
|
||||
version: string;
|
||||
modLoaders: Array<{ id: string }>;
|
||||
};
|
||||
files: Array<{ projectID: number; fileID: number }>;
|
||||
}
|
||||
|
||||
export class CurseForge implements XPlatform {
|
||||
async getinfo(manifest: object): Promise<modpack_info> {
|
||||
let result: modpack_info = Object.create({});
|
||||
const local_manifest = manifest as CurseForgeManifest;
|
||||
if (result && local_manifest)
|
||||
result.minecraft = local_manifest.minecraft.version;
|
||||
const id = local_manifest.minecraft.modLoaders[0].id;
|
||||
const loader_all = id.match(/(.*)-/) as RegExpMatchArray;
|
||||
result.loader = loader_all[1];
|
||||
result.loader_version = id.replace(loader_all[0], "");
|
||||
return result;
|
||||
}
|
||||
|
||||
async downloadfile(manifest: object, path: string): Promise<void> {
|
||||
const local_manifest = manifest as CurseForgeManifest;
|
||||
const FileID = JSON.stringify({
|
||||
fileIds: local_manifest.files.map(
|
||||
(file: { fileID: number }) => file.fileID
|
||||
),
|
||||
});
|
||||
let tmp: [string, string] | string[][] = [];
|
||||
await got
|
||||
.post(cf_url + "/v1/mods/files", {
|
||||
body: FileID,
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"x-api-key":
|
||||
"$2a$10$ydk0TLDG/Gc6uPMdz7mad.iisj2TaMDytVcIW4gcVP231VKngLBKy",
|
||||
"User-Agent": "DeEarthX",
|
||||
},
|
||||
})
|
||||
.json()
|
||||
.then((res: any) => {
|
||||
res.data.forEach(
|
||||
(e: { fileName: string; downloadUrl: null | string }) => {
|
||||
if (e.fileName.endsWith(".zip") || e.downloadUrl == null) {
|
||||
return;
|
||||
}
|
||||
const unpath = join(path + "/mods/", e.fileName);
|
||||
if (usemirror) {
|
||||
tmp.push([
|
||||
"https://mod.mcimirror.top" + new URL(e.downloadUrl).pathname,
|
||||
unpath,
|
||||
]);
|
||||
} else {
|
||||
tmp.push([e.downloadUrl, unpath]);
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
await fastdownload(tmp as unknown as [string, string]); //下载文件
|
||||
}
|
||||
}
|
||||
42
backend/src/platform/index.ts
Normal file
42
backend/src/platform/index.ts
Normal file
@@ -0,0 +1,42 @@
|
||||
import { CurseForge } from "./curseforge.js";
|
||||
import { MCBBS } from "./mcbbs.js";
|
||||
import { Modrinth } from "./modrinth.js";
|
||||
|
||||
export interface XPlatform {
|
||||
getinfo(manifest: object): Promise<modpack_info>;
|
||||
downloadfile(manifest: object,path:string): Promise<void>;
|
||||
}
|
||||
|
||||
export interface modpack_info {
|
||||
minecraft: string;
|
||||
loader: string;
|
||||
loader_version: string;
|
||||
}
|
||||
|
||||
export function platform(plat: string | undefined): XPlatform {
|
||||
let platform: XPlatform = Object.create({});
|
||||
switch (plat) {
|
||||
case "curseforge":
|
||||
platform = new CurseForge();
|
||||
break;
|
||||
case "modrinth":
|
||||
platform = new Modrinth();
|
||||
break;
|
||||
case "mcbbs":
|
||||
platform = new MCBBS();
|
||||
break;
|
||||
}
|
||||
return platform;
|
||||
}
|
||||
|
||||
export function what_platform(dud_files: Array<string>) {
|
||||
if (dud_files.includes("mcbbs.packmeta")) {
|
||||
return "mcbbs";
|
||||
} else if (dud_files.includes("manifest.json")) {
|
||||
return "curseforge";
|
||||
} else if (dud_files.includes("modrinth.index.json")) {
|
||||
return "modrinth";
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
20
backend/src/platform/mcbbs.ts
Normal file
20
backend/src/platform/mcbbs.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
import { CurseForgeManifest } from "./curseforge.js";
|
||||
import { modpack_info, XPlatform } from "./index.js";
|
||||
|
||||
interface MCBBSManifest extends CurseForgeManifest {}
|
||||
|
||||
export class MCBBS implements XPlatform {
|
||||
async getinfo(manifest: object): Promise<modpack_info> {
|
||||
const result: modpack_info = Object.create({});
|
||||
const local_manifest = manifest as MCBBSManifest;
|
||||
if (result && local_manifest)
|
||||
result.minecraft = local_manifest.minecraft.version;
|
||||
const id = local_manifest.minecraft.modLoaders[0].id;
|
||||
const loader_all = id.match(/(.*)-/) as RegExpMatchArray;
|
||||
result.loader = loader_all[1];
|
||||
result.loader_version = id.replace(loader_all[0], "");
|
||||
return result;
|
||||
}
|
||||
|
||||
async downloadfile(urls: [string, string]): Promise<void> {}
|
||||
}
|
||||
49
backend/src/platform/modrinth.ts
Normal file
49
backend/src/platform/modrinth.ts
Normal file
@@ -0,0 +1,49 @@
|
||||
import fs from "node:fs";
|
||||
import { mr_fastdownload, usemirror } from "../utils/utils.js";
|
||||
import { modpack_info, XPlatform } from "./index.js";
|
||||
import { join } from "node:path";
|
||||
|
||||
interface ModrinthManifest {
|
||||
files: Array<{ path: string; downloads: string[]; fileSize: number; }>;
|
||||
dependencies: {
|
||||
minecraft: string;
|
||||
forge: string;
|
||||
neoforge: string;
|
||||
"fabric-loader": string;
|
||||
[key: string]: string;
|
||||
};
|
||||
}
|
||||
|
||||
export class Modrinth implements XPlatform {
|
||||
async getinfo(manifest: object): Promise<modpack_info> {
|
||||
let result: modpack_info = Object.create({});
|
||||
const local_manifest = manifest as ModrinthManifest;
|
||||
const depkey = Object.keys(local_manifest.dependencies);
|
||||
const loader = ["forge", "neoforge", "fabric-loader"];
|
||||
result.minecraft = local_manifest.dependencies.minecraft;
|
||||
for (let i = 0; i < depkey.length; i++) {
|
||||
const key = depkey[i];
|
||||
if (key !== "minecraft" && loader.includes(key)) {
|
||||
result.loader = key;
|
||||
result.loader_version = local_manifest.dependencies[key];
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
async downloadfile(manifest: object,path:string): Promise<void> {
|
||||
const index = manifest as ModrinthManifest;
|
||||
let tmp: [string, string, string][] = []
|
||||
index.files.forEach(async (e: { path: string; downloads: string[]; fileSize: number;}) => {
|
||||
if (e.path.endsWith(".zip")) {
|
||||
return;
|
||||
}
|
||||
const unpath = join(path,e.path)
|
||||
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])
|
||||
}
|
||||
}
|
||||
38
backend/src/utils/config.ts
Normal file
38
backend/src/utils/config.ts
Normal file
@@ -0,0 +1,38 @@
|
||||
import fs from "fs";
|
||||
interface IConfig {
|
||||
mirror: {
|
||||
bmclapi: boolean;
|
||||
mcimirror: boolean;
|
||||
};
|
||||
filter: {
|
||||
hashes: boolean;
|
||||
dexpub: boolean;
|
||||
mixins: boolean;
|
||||
};
|
||||
}
|
||||
|
||||
export class Config {
|
||||
private readonly default_config: IConfig = {
|
||||
mirror: {
|
||||
bmclapi: true,
|
||||
mcimirror: true,
|
||||
},
|
||||
filter: {
|
||||
hashes: true,
|
||||
dexpub: false,
|
||||
mixins: true,
|
||||
},
|
||||
};
|
||||
config(): IConfig {
|
||||
if (!fs.existsSync("./config.json")) {
|
||||
fs.writeFileSync("./config.json", JSON.stringify(this.default_config));
|
||||
return this.default_config;
|
||||
}
|
||||
return JSON.parse(fs.readFileSync("./config.json", "utf-8"));
|
||||
}
|
||||
static write_config(config: IConfig) {
|
||||
fs.writeFileSync("./config.json", JSON.stringify(config));
|
||||
}
|
||||
}
|
||||
|
||||
export default new Config().config();
|
||||
14
backend/src/utils/utils.ts
Normal file
14
backend/src/utils/utils.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import config from "./config.js";
|
||||
|
||||
export class Utils{
|
||||
public modrinth_url: string;
|
||||
public curseforge_url: string;
|
||||
constructor(){
|
||||
this.modrinth_url = "https://api.modrinth.com"
|
||||
this.curseforge_url = "https://api.curseforge.com"
|
||||
if(config.mirror.mcimirror){
|
||||
this.modrinth_url = "https://mod.mcimirror.top/modrinth"
|
||||
this.curseforge_url = "https://mod.mcimirror.top/curseforge"
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user