classes
This commit is contained in:
185
src/curse.ts
185
src/curse.ts
@ -1,5 +1,6 @@
|
|||||||
import { https } from "follow-redirects";
|
import { https } from "follow-redirects";
|
||||||
import fs from "fs";
|
import fs from "fs";
|
||||||
|
import {modBase, config} from "./modBase";
|
||||||
interface modLockElement {
|
interface modLockElement {
|
||||||
fileId: number;
|
fileId: number;
|
||||||
url: string;
|
url: string;
|
||||||
@ -10,111 +11,111 @@ interface Dependency {
|
|||||||
readonly addonId: number;
|
readonly addonId: number;
|
||||||
readonly type: number;
|
readonly type: number;
|
||||||
}
|
}
|
||||||
let mods_lock: modLockMap;
|
class curse extends modBase {
|
||||||
let downloadStarted: boolean = false;
|
private dep: modLockMap = new Map();
|
||||||
let globCallback;
|
private downloadStarted: boolean = false;
|
||||||
let config;
|
constructor(private modsLock: modLockMap, config: config, callback: Function) {
|
||||||
let dep: modLockMap = new Map();
|
super(config, callback);
|
||||||
function main() {
|
if(config.mods.curse.length === 0) callback("curse", {});
|
||||||
mods_lock = new Map(Object.entries(mods_lock));
|
config.mods.curse.forEach((mod: string) => {
|
||||||
if(config.mods.curse.length === 0) globCallback("curse", {});
|
this.getData(`search?categoryId=0&gameId=432&gameVersion=${encodeURI(config.gameVersion)}&index=0&pageSize=15&searchFilter=${encodeURI(mod)}§ionId=6&sort=0`, (result: Array<any>) => { // resolve projectID
|
||||||
config.mods.curse.forEach((mod: string) => {
|
let i = 0;
|
||||||
getData(`search?categoryId=0&gameId=432&gameVersion=${encodeURI(config.gameVersion)}&index=0&pageSize=15&searchFilter=${encodeURI(mod)}§ionId=6&sort=0`, (result: Array<any>) => { // resolve projectID
|
while(result[i].name !== mod) {
|
||||||
let i = 0;
|
++i;
|
||||||
while(result[i].name !== mod) {
|
if(i === result.length) {
|
||||||
++i;
|
console.log(`cursemod ${mod} not found`);
|
||||||
if(i === result.length) {
|
return;
|
||||||
console.log(`cursemod ${mod} not found`);
|
}
|
||||||
return;
|
}
|
||||||
|
this.resolveDep(result[i].id, () => {
|
||||||
|
this.downloadMods();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private resolveDepRecursionCount = 0;
|
||||||
|
private resolveDep(modId: number, callback: Function):void {
|
||||||
|
++this.resolveDepRecursionCount;
|
||||||
|
this.getData(`${modId}/files`, (files: Array<any>) => {
|
||||||
|
let rightVersion;
|
||||||
|
for(let i = files.length - 1; i >= 0; --i) {
|
||||||
|
let versionArray = files[i].gameVersion;
|
||||||
|
if(this.versionMatch(versionArray, this.config.gameVersion) && (this.versionMatch(versionArray, this.config.modloader) || this.modloaderMatch(versionArray, this.config.modloader))) {
|
||||||
|
rightVersion = files[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
resolveDep(result[i].id, downloadMods);
|
if(rightVersion === undefined) {
|
||||||
});
|
this.getData(String(modId), (mod: any) => {
|
||||||
});
|
console.log(`cursemod ${mod.name}: no version for the correct minecraft version and modloader found`);
|
||||||
}
|
});
|
||||||
|
return;
|
||||||
var resolveDepRecursionCount = 0;
|
|
||||||
function resolveDep(modId: number, callback: Function) {
|
|
||||||
++resolveDepRecursionCount;
|
|
||||||
getData(`${modId}/files`, (files: Array<any>) => {
|
|
||||||
let rightVersion: any;
|
|
||||||
for(let i = files.length - 1; i >= 0; --i) {
|
|
||||||
let versionArray = files[i].gameVersion;
|
|
||||||
if(versionMatch(versionArray, config.gameVersion) && (versionMatch(versionArray, config.modloader) || modloaderMatch(versionArray, config.modloader))) {
|
|
||||||
rightVersion = files[i];
|
|
||||||
}
|
}
|
||||||
}
|
this.dep.set(String(modId), {fileId: rightVersion.id, url: rightVersion.downloadUrl, filename: rightVersion.fileName});
|
||||||
if(rightVersion === undefined) {
|
rightVersion.dependencies.forEach((mod: Dependency) => {
|
||||||
getData(String(modId), (mod: any) => {
|
if(mod.type !== 3) return;
|
||||||
console.log(`cursemod ${mod.name}: no version for the correct minecraft version and modloader found`);
|
this.resolveDep(mod.addonId, callback);
|
||||||
});
|
});
|
||||||
return;
|
--this.resolveDepRecursionCount;
|
||||||
}
|
if(this.resolveDepRecursionCount == 0) callback();
|
||||||
dep.set(String(modId), {fileId: rightVersion.id, url: rightVersion.downloadUrl, filename: rightVersion.fileName});
|
|
||||||
rightVersion.dependencies.forEach((mod: Dependency) => {
|
|
||||||
if(mod.type !== 3) return;
|
|
||||||
resolveDep(mod.addonId, callback);
|
|
||||||
});
|
});
|
||||||
--resolveDepRecursionCount;
|
}
|
||||||
if(resolveDepRecursionCount == 0) callback();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function getData(url: string, callback: Function) {
|
private getData(url: string, callback: Function):void {
|
||||||
https.get(`https://addons-ecs.forgesvc.net/api/v2/addon/${url}`, (resp) => {
|
https.get(`https://addons-ecs.forgesvc.net/api/v2/addon/${url}`, (resp) => {
|
||||||
let data: string = '';
|
let data: string = '';
|
||||||
resp.on('data', (chunk) => {
|
resp.on('data', (chunk) => {
|
||||||
data += chunk;
|
data += chunk;
|
||||||
});
|
});
|
||||||
resp.on("end", () => {
|
resp.on("end", () => {
|
||||||
callback(JSON.parse(data));
|
callback(JSON.parse(data));
|
||||||
});
|
});
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function versionMatch(versionArray, gameVersion) {
|
|
||||||
let gameVersionMatch = false;
|
|
||||||
versionArray.forEach(version => {
|
|
||||||
gameVersionMatch = gameVersionMatch || version == gameVersion;
|
|
||||||
});
|
|
||||||
return gameVersionMatch;
|
|
||||||
}
|
|
||||||
|
|
||||||
function modloaderMatch(versionArray, modloaderVersion) {
|
|
||||||
for(let i = 0; i < versionArray.length; ++i) {
|
|
||||||
if(/^[a-zA-Z]+$/.test(versionArray[i]) && versionArray[i] != modloaderVersion) return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
function downloadMods() {
|
|
||||||
if(!downloadStarted) {
|
|
||||||
downloadStarted = true;
|
|
||||||
globCallback("curse", Object.fromEntries(dep));
|
|
||||||
dep.forEach((mod: modLockElement, modId: string) => {
|
|
||||||
let path = modPath(mod)
|
|
||||||
if(mods_lock.has(modId)) {
|
|
||||||
if(mods_lock.get(modId)!.fileId === mod.fileId) return;
|
|
||||||
fs.unlink(path, () => {});
|
|
||||||
}
|
|
||||||
downloadFile(mod.url, path);
|
|
||||||
});
|
|
||||||
mods_lock.forEach((mod: modLockElement, modId: string) => {
|
|
||||||
if(!dep.has(modId)) fs.unlink(modPath(mod), () => {})
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
function downloadFile(url: string, dest: string) {
|
versionMatch(versionArray, gameVersion):boolean {
|
||||||
let file = fs.createWriteStream(dest);
|
let gameVersionMatch = false;
|
||||||
console.log(`downloading ${url}`);
|
versionArray.forEach(version => {
|
||||||
let request = https.get(url, (response) => {
|
gameVersionMatch = gameVersionMatch || version == gameVersion;
|
||||||
// check if response is success
|
});
|
||||||
if (response.statusCode !== 200) {
|
return gameVersionMatch;
|
||||||
throw response.statusCode;
|
}
|
||||||
|
|
||||||
|
private modloaderMatch(versionArray: Array<string>, modloaderVersion: string):boolean {
|
||||||
|
for(let i = 0; i < versionArray.length; ++i) {
|
||||||
|
if(/^[a-zA-Z]+$/.test(versionArray[i]) && versionArray[i] != modloaderVersion) return false;
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
response.pipe(file);
|
private downloadMods():void {
|
||||||
|
if(!this.downloadStarted) {
|
||||||
|
this.downloadStarted = true;
|
||||||
|
this.callback("curse", Object.fromEntries(this.dep));
|
||||||
|
this.dep.forEach((mod: modLockElement, modId: string) => {
|
||||||
|
let path = this.modPath(mod)
|
||||||
|
if(this.modsLock.has(modId)) {
|
||||||
|
if(this.modsLock.get(modId)!.fileId === mod.fileId) return;
|
||||||
|
fs.unlink(path, () => {});
|
||||||
|
}
|
||||||
|
this.downloadFile(mod.url, path);
|
||||||
|
});
|
||||||
|
this.modsLock.forEach((mod: modLockElement, modId: string) => {
|
||||||
|
if(!this.dep.has(modId)) fs.unlink(this.modPath(mod), () => {})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private downloadFile(url: string, dest: string):void {
|
||||||
|
let file = fs.createWriteStream(dest);
|
||||||
|
console.log(`downloading ${url}`);
|
||||||
|
let request = https.get(url, (response) => {
|
||||||
|
// check if response is success
|
||||||
|
if (response.statusCode !== 200) {
|
||||||
|
throw response.statusCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
response.pipe(file);
|
||||||
});
|
});
|
||||||
|
|
||||||
// close() is async, call cb after close completes
|
// close() is async, call cb after close completes
|
||||||
@ -131,10 +132,6 @@ function downloadFile(url: string, dest: string) {
|
|||||||
throw err;
|
throw err;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = function(mods_lock_p, _config, callback) {
|
export = curse;
|
||||||
mods_lock = mods_lock_p;
|
|
||||||
globCallback = callback;
|
|
||||||
config = _config;
|
|
||||||
main();
|
|
||||||
};
|
|
||||||
|
|||||||
152
src/git.ts
152
src/git.ts
@ -2,6 +2,7 @@ import git from "gift";
|
|||||||
import childProcess from "child_process";
|
import childProcess from "child_process";
|
||||||
import fs from "fs";
|
import fs from "fs";
|
||||||
import g2js from "gradle-to-js/lib/parser";
|
import g2js from "gradle-to-js/lib/parser";
|
||||||
|
import {modBase, config} from "./modBase";
|
||||||
interface modLockElement {
|
interface modLockElement {
|
||||||
commitId: string;
|
commitId: string;
|
||||||
url: string;
|
url: string;
|
||||||
@ -11,91 +12,84 @@ type modLockMap = Map<string, modLockElement>;
|
|||||||
interface commit {
|
interface commit {
|
||||||
id: string;
|
id: string;
|
||||||
}
|
}
|
||||||
let modsLock: modLockMap;
|
class gitMods extends modBase {
|
||||||
let globCallback: Function;
|
private loopCounter: number = 0;
|
||||||
let loopCounter: number = 0;
|
constructor(private modsLock: modLockMap, config: config, callback: Function) {
|
||||||
let config;
|
super(config, callback);
|
||||||
function main () {
|
let deleteMods: modLockMap = new Map(this.modsLock);
|
||||||
modsLock = new Map(Object.entries(modsLock));
|
let cacheDir = process.env.XDG_CACHE_HOME;
|
||||||
let deleteMods: modLockMap = new Map(modsLock);
|
if(cacheDir == null) cacheDir = `${process.env.HOME}/.cache`;
|
||||||
let cacheDir = process.env.XDG_CACHE_HOME;
|
let repoPathRoot = `${cacheDir}/minecraft-mod-packager`;
|
||||||
if(cacheDir == null) cacheDir = `${process.env.HOME}/.cache`;
|
config.mods.git.forEach((gitRepo) => {
|
||||||
let repoPathRoot = `${cacheDir}/minecraft-mod-packager`;
|
++this.loopCounter;
|
||||||
config.mods.git.forEach((gitRepo) => {
|
deleteMods.delete(gitRepo.url);
|
||||||
++loopCounter;
|
let repoPath = `${repoPathRoot}/${gitRepo.url.replace("://", "+")}/${gitRepo.branch}`;
|
||||||
deleteMods.delete(gitRepo.url);
|
fs.access(repoPath, (err) => {
|
||||||
let repoPath = `${repoPathRoot}/${gitRepo.url.replace("://", "+")}/${gitRepo.branch}`;
|
if(err) {
|
||||||
fs.access(repoPath, (err) => {
|
if(err.code !== "ENOENT") throw err;
|
||||||
if(err) {
|
console.log(`cloning git repo ${gitRepo.url}`);
|
||||||
if(err.code !== "ENOENT") throw err;
|
git.clone(gitRepo.url, repoPath, undefined, gitRepo.branch, (err: Error, repo) => {
|
||||||
console.log(`cloning git repo ${gitRepo.url}`);
|
if(err) throw err;
|
||||||
git.clone(gitRepo.url, repoPath, undefined, gitRepo.branch, (err: Error, repo) => {
|
this.build(repo, repoPath, gitRepo);
|
||||||
if(err) throw err;
|
});
|
||||||
build(repo, repoPath, gitRepo);
|
}
|
||||||
});
|
else {
|
||||||
}
|
let repo = git(repoPath);
|
||||||
else {
|
console.log(`pulling git repo ${gitRepo.url}`);
|
||||||
let repo = git(repoPath);
|
repo.pull(["origin"], gitRepo.branch, (err: Error) => {
|
||||||
console.log(`pulling git repo ${gitRepo.url}`);
|
if(err) throw err;
|
||||||
repo.pull(["origin"], gitRepo.branch, (err: Error) => {
|
this.build(repo, repoPath, gitRepo);
|
||||||
if(err) throw err;
|
});
|
||||||
build(repo, repoPath, gitRepo);
|
}
|
||||||
});
|
});
|
||||||
}
|
|
||||||
});
|
});
|
||||||
});
|
deleteMods.forEach((mod, url) => {
|
||||||
deleteMods.forEach((mod, url) => {
|
this.modsLock.delete(url);
|
||||||
modsLock.delete(url);
|
fs.unlink(this.modPath(mod), (err) => {
|
||||||
fs.unlink(modPath(mod), (err) => {
|
|
||||||
if(err) throw err;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
mayCb();
|
|
||||||
}
|
|
||||||
|
|
||||||
function build(repo, repoPath, gitRepo):void {
|
|
||||||
let newLock: modLockElement;
|
|
||||||
newLock = modsLock.get(gitRepo.url) ?? {} as modLockElement;
|
|
||||||
modsLock.set(gitRepo.url, newLock);
|
|
||||||
repo.current_commit((err: Error, commit: commit) => {
|
|
||||||
if(err) throw err;
|
|
||||||
if(commit.id === newLock.commitId) cbDecrease();
|
|
||||||
else {
|
|
||||||
newLock.commitId = commit.id;
|
|
||||||
console.log(`buidling ${gitRepo.url}`);
|
|
||||||
childProcess.execFile("gradle", ["build"], {cwd: repoPath}, (err) => {
|
|
||||||
if(err) throw err;
|
if(err) throw err;
|
||||||
let buildPath = `${repoPath}/build/libs`;
|
});
|
||||||
fs.readFile(`${repoPath}/gradle.properties`, "utf-8", (err, data) => {
|
});
|
||||||
|
this.mayCb();
|
||||||
|
}
|
||||||
|
|
||||||
|
private build(repo, repoPath, gitRepo):void {
|
||||||
|
let newLock: modLockElement;
|
||||||
|
newLock = this.modsLock.get(gitRepo.url) ?? {} as modLockElement;
|
||||||
|
this.modsLock.set(gitRepo.url, newLock);
|
||||||
|
repo.current_commit((err: Error, commit: commit) => {
|
||||||
|
if(err) throw err;
|
||||||
|
if(commit.id === newLock.commitId) this.cbDecrease();
|
||||||
|
else {
|
||||||
|
newLock.commitId = commit.id;
|
||||||
|
console.log(`buidling ${gitRepo.url}`);
|
||||||
|
childProcess.execFile("gradle", ["build"], {cwd: repoPath}, (err) => {
|
||||||
if(err) throw err;
|
if(err) throw err;
|
||||||
g2js.parseText(data).then((gradleProp) => {
|
let buildPath = `${repoPath}/build/libs`;
|
||||||
if(newLock.filename != null) fs.unlink(modPath(newLock), (err) => {
|
fs.readFile(`${repoPath}/gradle.properties`, "utf-8", (err, data) => {
|
||||||
if(err) throw err;
|
if(err) throw err;
|
||||||
|
g2js.parseText(data).then((gradleProp) => {
|
||||||
|
if(newLock.filename != null) fs.unlink(this.modPath(newLock), (err) => {
|
||||||
|
if(err) throw err;
|
||||||
|
});
|
||||||
|
newLock.filename = `${gradleProp.archives_base_name}-${gradleProp.mod_version}.jar`;
|
||||||
|
fs.copyFile(`${buildPath}/${newLock.filename}`, this.modPath(newLock), (err) => {
|
||||||
|
if(err) throw err;
|
||||||
|
});
|
||||||
|
this.cbDecrease();
|
||||||
});
|
});
|
||||||
newLock.filename = `${gradleProp.archives_base_name}-${gradleProp.mod_version}.jar`;
|
|
||||||
fs.copyFile(`${buildPath}/${newLock.filename}`, modPath(newLock), (err) => {
|
|
||||||
if(err) throw err;
|
|
||||||
});
|
|
||||||
cbDecrease();
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
}
|
||||||
}
|
});
|
||||||
});
|
}
|
||||||
}
|
|
||||||
|
|
||||||
function cbDecrease():void {
|
private cbDecrease():void {
|
||||||
--loopCounter;
|
--this.loopCounter;
|
||||||
mayCb();
|
this.mayCb();
|
||||||
}
|
}
|
||||||
|
|
||||||
function mayCb():void {
|
private mayCb():void {
|
||||||
if(loopCounter <= 0) globCallback("git", Object.fromEntries(modsLock));
|
if(this.loopCounter <= 0) this.callback("git", Object.fromEntries(this.modsLock));
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = (mods_lock_p, _config, cb) => {
|
|
||||||
globCallback = cb;
|
|
||||||
modsLock = mods_lock_p;
|
|
||||||
config = _config;
|
|
||||||
main()
|
|
||||||
}
|
}
|
||||||
|
export = gitMods;
|
||||||
|
|||||||
@ -1,6 +1,10 @@
|
|||||||
const jsonMinify = require("node-json-minify");
|
import jsonMinify from "node-json-minify";
|
||||||
const fs = require("fs");
|
import fs from "fs";
|
||||||
let config;
|
import {config} from "./modBase";
|
||||||
|
import curse from "./curse";
|
||||||
|
import git from "./git";
|
||||||
|
let config: config;
|
||||||
|
let modules = ["curse", "git"];
|
||||||
switch(process.argv.length) {
|
switch(process.argv.length) {
|
||||||
case 3:
|
case 3:
|
||||||
process.chdir(process.argv[2]);
|
process.chdir(process.argv[2]);
|
||||||
@ -18,14 +22,14 @@ try {
|
|||||||
}
|
}
|
||||||
catch(err) {
|
catch(err) {
|
||||||
if(err.errno !== -2) throw err;
|
if(err.errno !== -2) throw err;
|
||||||
modsLock = {curse: {}, git: {}};
|
modsLock = {};
|
||||||
}
|
}
|
||||||
const numberCallback = 2;
|
const numberCallback = modules.length;
|
||||||
let callbackCounter = 0;
|
let callbackCounter = 0;
|
||||||
require("./curse")(modsLock.curse, config, finnish);
|
new git(new Map(Object.entries(modsLock.git ?? {})), config, finnish);
|
||||||
require("./git.js")(modsLock.git, config, finnish);
|
new curse(new Map(Object.entries(modsLock.curse ?? {})), config, finnish);
|
||||||
|
|
||||||
function finnish(name, data) {
|
function finnish(name: string, data) {
|
||||||
save_mods_lock[name] = data;
|
save_mods_lock[name] = data;
|
||||||
if(++callbackCounter == numberCallback) {
|
if(++callbackCounter == numberCallback) {
|
||||||
fs.writeFile(modLockPath, JSON.stringify(save_mods_lock), (err) => {
|
fs.writeFile(modLockPath, JSON.stringify(save_mods_lock), (err) => {
|
||||||
18
src/modBase.ts
Normal file
18
src/modBase.ts
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
export interface config {
|
||||||
|
gameVersion: string;
|
||||||
|
modloader: string;
|
||||||
|
mods: {
|
||||||
|
curse: Array<string>;
|
||||||
|
git: Array<{
|
||||||
|
url: string;
|
||||||
|
branch: string;
|
||||||
|
}>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export class modBase {
|
||||||
|
constructor(protected config: config, protected callback: Function) {
|
||||||
|
}
|
||||||
|
protected modPath(mod: any) {
|
||||||
|
return `mods/${mod.filename}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,3 +0,0 @@
|
|||||||
function modPath(mod: any) {
|
|
||||||
return `mods/${mod.filename}`;
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user