mirror of
https://github.com/clusterio/clusterio.git
synced 2026-11-12 23:04:52 +09:00
Fixed mod manager not exiting after downloading mods
This commit is contained in:
1 parent
e4c276054b
commit
447766c752
4 files changed
+206
-163
No files matched your search
@@ -158,7 +158,7 @@ if (!command || command == "help" || command == "--help") {
|
||||
});
|
||||
|
||||
displayLines.forEach(line => console.log(line));
|
||||
process.exit(1);
|
||||
process.exit(0);
|
||||
} else if (command == "manage"){
|
||||
// console.log("Launching mod manager");
|
||||
//const fullUsage = 'node client.js manage [instance, "shared"] ["mods", "config"] ...';
|
||||
@@ -175,20 +175,26 @@ if (!command || command == "help" || command == "--help") {
|
||||
const action = process.argv[5] || "";
|
||||
if(instance){
|
||||
if(tool == "mods"){
|
||||
// allow managing mods
|
||||
if(action == "list"){
|
||||
modManager.listMods(instance);
|
||||
} else if(action == "search"){
|
||||
modManager.findMods(process.argv[6]);
|
||||
} else if(action == "add" || action == "download"){
|
||||
modManager.addMod(process.argv[6], instance);
|
||||
} else if(action == "remove" || action == "rm" || action == "delete"){
|
||||
modManager.removeMod(process.argv[6], instance);
|
||||
} else if(action == "update"){
|
||||
modManager.updateAllMods();
|
||||
} else {
|
||||
usage(instance, tool);
|
||||
}
|
||||
(async function(){try{
|
||||
// allow managing mods
|
||||
if(action == "list"){
|
||||
console.log(await modManager.listMods(instance));
|
||||
} else if(action == "search"){
|
||||
console.log(await modManager.findMods(process.argv[6]));
|
||||
} else if(action == "add" || action == "download"){
|
||||
await modManager.addMod(process.argv[6], instance);
|
||||
} else if(action == "remove" || action == "rm" || action == "delete"){
|
||||
await modManager.removeMod(process.argv[6], instance);
|
||||
} else if(action == "update"){
|
||||
await modManager.updateAllMods();
|
||||
} else {
|
||||
usage(instance, tool);
|
||||
}
|
||||
process.exit(0);
|
||||
}catch(e){
|
||||
console.log("Got error from modManager:")
|
||||
console.log(e);
|
||||
}})();
|
||||
} else if(tool == "config"){
|
||||
// allow managing the config
|
||||
if(action == "list" || action == "show" || action == "display"){
|
||||
@@ -213,7 +219,7 @@ if (!command || command == "help" || command == "--help") {
|
||||
console.log('Usage:');
|
||||
usage(instance);
|
||||
}
|
||||
// process.exit(1);
|
||||
// process.exit(0);
|
||||
} else if (command == "delete") {
|
||||
if (!process.argv[3]) {
|
||||
console.error("Usage: node client.js delete [instance]");
|
||||
@@ -221,10 +227,10 @@ if (!command || command == "help" || command == "--help") {
|
||||
} else if (typeof process.argv[3] == "string" && fs.existsSync("./instances/" + process.argv[3]) && process.argv[3] != "/" && process.argv[3] != "") {
|
||||
fileOps.deleteFolderRecursiveSync("./instances/" + process.argv[3]);
|
||||
console.log("Deleted instance " + process.argv[3]);
|
||||
process.exit(1);
|
||||
process.exit(0);
|
||||
} else {
|
||||
console.error("Instance not found: " + process.argv[3]);
|
||||
process.exit(1);
|
||||
process.exit(0);
|
||||
}
|
||||
} else if (command == "download") {
|
||||
console.log("Downloading mods...");
|
||||
@@ -238,6 +244,7 @@ if (!command || command == "help" || command == "--help") {
|
||||
https.get(url, function(response) {
|
||||
response.pipe(file);
|
||||
console.log("Downloaded "+name);
|
||||
process.exit(0);
|
||||
});
|
||||
}
|
||||
} else if (command == "start" && instance === undefined) {
|
||||
|
||||
+178
-144
@@ -11,6 +11,7 @@ const fs = require("fs");
|
||||
const https = require('follow-redirects').https;
|
||||
const factorioAPI = require("node-factorio-api");
|
||||
const sLog = require("single-line-log").stdout;
|
||||
const query = require('cli-interact').getYesNo;
|
||||
|
||||
const fileOps = require("_app/fileOps");
|
||||
const config = require("./../../config");
|
||||
@@ -35,56 +36,62 @@ modManager.listMods("shared");
|
||||
// console.logs mods located in /sharedMods as a nice table
|
||||
*/
|
||||
module.exports.listMods = function(instance){
|
||||
if(instance && instances.includes(instance)){
|
||||
factorioAPI.init(false, 'instances/'+instance+'/instanceMods', 'instances/'+instance+'/saves', config.factorio_version);
|
||||
factorioAPI.authenticate({
|
||||
username: config.username,
|
||||
token: config.token,
|
||||
require_ownership: false
|
||||
}).then(token => {
|
||||
console.log("* Currently installed:");
|
||||
factorioAPI.readModZips().then(list => {
|
||||
console.log(asTable(list.map(mod => {
|
||||
return {
|
||||
name:(mod.title || mod.name),
|
||||
version:mod.version,
|
||||
date:mod.date,
|
||||
factorio_ver:mod.factorio_version,
|
||||
author:mod.author,
|
||||
}
|
||||
})));
|
||||
return new Promise((resolve, reject) => {
|
||||
if(instance && instances.includes(instance)){
|
||||
factorioAPI.init(false, 'instances/'+instance+'/instanceMods', 'instances/'+instance+'/saves', config.factorio_version);
|
||||
factorioAPI.authenticate({
|
||||
username: config.username,
|
||||
token: config.token,
|
||||
require_ownership: false
|
||||
}).then(token => {
|
||||
console.log("* Currently installed:");
|
||||
factorioAPI.readModZips().then(list => {
|
||||
console.log(asTable(list.map(mod => {
|
||||
return {
|
||||
name:(mod.title || mod.name),
|
||||
version:mod.version,
|
||||
date:mod.date,
|
||||
factorio_ver:mod.factorio_version,
|
||||
author:mod.author,
|
||||
}
|
||||
})));
|
||||
});
|
||||
// Had issues earlier due to bug in node-factorio-api, see https://github.com/Danacus/node-factorio-api/issues/2
|
||||
// bug is resolved, thanks to @Danacus and @brotherpot
|
||||
factorioAPI.getModsFromSaves().then(list => {
|
||||
console.log("* Mods used in save:");
|
||||
console.log(asTable(list[0].mods))
|
||||
});
|
||||
}).catch(reason => {
|
||||
console.log("Failed to authenticate to factorio.com! Please check your connection and the username+token used for authentication in config.json");
|
||||
resolve();
|
||||
});
|
||||
// Had issues earlier due to bug in node-factorio-api, see https://github.com/Danacus/node-factorio-api/issues/2
|
||||
// bug is resolved, thanks to @Danacus and @brotherpot
|
||||
factorioAPI.getModsFromSaves().then(list => {
|
||||
console.log("* Mods used in save:");
|
||||
console.log(asTable(list[0].mods))
|
||||
} else {
|
||||
// list shared mods in /sharedMods/
|
||||
factorioAPI.init(false, 'sharedMods/', '', config.factorio_version);
|
||||
factorioAPI.authenticate({
|
||||
username: config.username,
|
||||
token: config.token,
|
||||
require_ownership: false
|
||||
}).then(() => {
|
||||
console.log("\r\n")
|
||||
console.log("* Mods shared by all instances:")
|
||||
factorioAPI.getInstalledMods().then(mods => {
|
||||
console.log(asTable(mods));
|
||||
resolve();
|
||||
});
|
||||
}).catch(e => {
|
||||
reject(new Error(e));
|
||||
});
|
||||
}).catch(reason => {
|
||||
console.log("Failed to authenticate to factorio.com! Please check your connection and the username+token used for authentication in config.json");
|
||||
});
|
||||
} else {
|
||||
// list shared mods in /sharedMods/
|
||||
factorioAPI.init(false, 'sharedMods/', '', config.factorio_version);
|
||||
factorioAPI.authenticate({
|
||||
username: config.username,
|
||||
token: config.token,
|
||||
require_ownership: false
|
||||
}).then(() => {
|
||||
console.log("\r\n")
|
||||
console.log("* Mods shared by all instances:")
|
||||
factorioAPI.getInstalledMods().then(mods => {
|
||||
console.log(asTable(mods));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// get JSON data about GH releases
|
||||
/*let res = syncRequest('GET', 'https://api.github.com/repos/Danielv123/factorioClusterioMod/releases', {"headers":{"User-Agent":"Fuck you for requiring user agents!"}});
|
||||
let url = JSON.parse(res.getBody())[0].assets[0].browser_download_url;
|
||||
let name = JSON.parse(res.getBody())[0].assets[0].name;
|
||||
console.log(JSON.parse(res.getBody()))
|
||||
*/
|
||||
}
|
||||
|
||||
// get JSON data about GH releases
|
||||
/*let res = syncRequest('GET', 'https://api.github.com/repos/Danielv123/factorioClusterioMod/releases', {"headers":{"User-Agent":"Fuck you for requiring user agents!"}});
|
||||
let url = JSON.parse(res.getBody())[0].assets[0].browser_download_url;
|
||||
let name = JSON.parse(res.getBody())[0].assets[0].name;
|
||||
console.log(JSON.parse(res.getBody()))
|
||||
*/
|
||||
});
|
||||
}
|
||||
/**
|
||||
Searches mods.factorio.com for mods matching a search term and prints
|
||||
@@ -93,116 +100,143 @@ the results to console as a neat looking table
|
||||
@param {string} searchTerm What to search for
|
||||
*/
|
||||
module.exports.findMods = function(searchTerm){
|
||||
factorioAPI.init(false);
|
||||
factorioAPI.authenticate({
|
||||
username: config.username,
|
||||
token: config.token,
|
||||
require_ownership: false
|
||||
}).then(token => {
|
||||
factorioAPI.searchMods(searchTerm).then(mods => {
|
||||
console.log(asTable(mods.reverse().map(mod => {
|
||||
return {
|
||||
title:ellipse(mod.title, 50),
|
||||
name:ellipse(mod.name, 30),
|
||||
downloads:mod.downloads_count,
|
||||
updated: moment(mod.updated_at).format("DD.MM.YY"),
|
||||
latest_version: mod.latest_release.version,
|
||||
owner:mod.owner,
|
||||
//license: mod.license_name,
|
||||
}
|
||||
})))
|
||||
})
|
||||
return new Promise((resolve, reject) => {
|
||||
factorioAPI.init(false);
|
||||
factorioAPI.authenticate({
|
||||
username: config.username,
|
||||
token: config.token,
|
||||
require_ownership: false
|
||||
}).then(token => {
|
||||
factorioAPI.searchMods(searchTerm).then(mods => {
|
||||
let result = asTable(mods.reverse().map(mod => {
|
||||
return {
|
||||
title:ellipse(mod.title, 50),
|
||||
name:ellipse(mod.name, 30),
|
||||
downloads:mod.downloads_count,
|
||||
updated: moment(mod.updated_at).format("DD.MM.YY"),
|
||||
latest_version: mod.latest_release.version,
|
||||
owner:mod.owner,
|
||||
//license: mod.license_name,
|
||||
}
|
||||
}));
|
||||
resolve(result);
|
||||
// console.log(result);
|
||||
});
|
||||
}).catch(e => {
|
||||
if(e.contains("Insufficient information")) console.log("We are missing some parameters required for logging in! Make sure your factorio username and token are specified in config.json.");
|
||||
reject(new Error(e));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
module.exports.addMod = function(term, instance){
|
||||
if(instance == "shared"){ // modDirectory has to end in /
|
||||
var modDirectory = "sharedMods/";
|
||||
} else {
|
||||
var modDirectory = "instances/"+instance+"/instanceMods/";
|
||||
}
|
||||
if(term && term.length > 0){
|
||||
if(term.includes("mods.factorio.com/mods/")){ // https://mods.factorio.com/mods/Danielv123/ChooChoo
|
||||
// treat it as a link download
|
||||
factorioAPI.init(false, modDirectory, "", config.factorio_version);
|
||||
factorioAPI.authenticate({
|
||||
username: config.username,
|
||||
token: config.token,
|
||||
require_ownership: false
|
||||
}).then(() => {
|
||||
factorioAPI.searchMods(term.split("/")[term.split("/").length-1]).then(body => {
|
||||
console.log("Im gonna download: "+body[0].name + " in version: " + body[0].latest_release.version);
|
||||
factorioAPI.downloadMod( {name: body[0].name, version: body[0].latest_release.version}).then(()=>{
|
||||
console.log("Mod downloaded");
|
||||
return new Promise((resolve, reject) => {
|
||||
if(instance == "shared"){ // modDirectory has to end in /
|
||||
var modDirectory = "sharedMods/";
|
||||
} else {
|
||||
var modDirectory = "instances/"+instance+"/instanceMods/";
|
||||
}
|
||||
if(term && term.length > 0){
|
||||
if(term.includes("mods.factorio.com/mods/")){ // https://mods.factorio.com/mods/Danielv123/ChooChoo
|
||||
// treat it as a link download
|
||||
factorioAPI.init(false, modDirectory, "", config.factorio_version);
|
||||
factorioAPI.authenticate({
|
||||
username: config.username,
|
||||
token: config.token,
|
||||
require_ownership: false
|
||||
}).then(() => {
|
||||
factorioAPI.searchMods(term.split("/")[term.split("/").length-1]).then(body => {
|
||||
console.log("Im gonna download: "+body[0].name + " in version: " + body[0].latest_release.version);
|
||||
factorioAPI.downloadMod( {name: body[0].name, version: body[0].latest_release.version}).then(()=>{
|
||||
console.log("Mod downloaded");
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
} else if(term.includes("github.com")){ // https://github.com/Danielv123/factorioClusterioMod
|
||||
// treat it as a github releases download
|
||||
let apiURL = "https://api.github.com/repos/" + term.split("/")[3] + "/" + term.split("/")[4] + "/releases"; // https://api.github.com/repos/Danielv123/factorioClusterioMod/releases
|
||||
|
||||
let res = syncRequest('GET', apiURL, {"headers":{"User-Agent":"Fuck you for requiring user agents!"}});
|
||||
let url = JSON.parse(res.getBody())[0].assets[0].browser_download_url;
|
||||
let name = JSON.parse(res.getBody())[0].assets[0].name;
|
||||
if(url) {
|
||||
console.log("Downloading " + url);
|
||||
let file = fs.createWriteStream(modDirectory + name);
|
||||
let bytesDownloaded = 0;
|
||||
let downloadStartTime = Date.now();
|
||||
https.get(url, function(response) {
|
||||
let bytesToDownload = response.headers['content-length'];
|
||||
response.pipe(file);
|
||||
response.on("data", chunk => {
|
||||
bytesDownloaded += chunk.length;
|
||||
let downloadTimeElapsed = Date.now() - downloadStartTime;
|
||||
let bytesPerSecond = bytesDownloaded / (downloadTimeElapsed/1000);
|
||||
let timeToComplete = Math.floor((bytesToDownload - bytesDownloaded)/bytesPerSecond);
|
||||
sLog("Downloading "+name+" "+(bytesDownloaded/bytesToDownload*100).toPrecision(3)+"% ("+formatBytes(bytesDownloaded)+" / "+formatBytes(bytesToDownload)+")\r\n"+
|
||||
"about "+timeToComplete+" seconds remaining ("+formatBytes(bytesPerSecond)+"/s)");
|
||||
}).on("end", x => {
|
||||
sLog.clear();
|
||||
console.log(" Downloaded in "+moment.utc(moment.duration(Date.now()-downloadStartTime).as('milliseconds')).format('mm:ss')); // because sLog.clear() doesn't seem to do the job of ending the line properly
|
||||
} else if(term.includes("github.com")){ // https://github.com/Danielv123/factorioClusterioMod
|
||||
// treat it as a github releases download
|
||||
let apiURL = "https://api.github.com/repos/" + term.split("/")[3] + "/" + term.split("/")[4] + "/releases"; // https://api.github.com/repos/Danielv123/factorioClusterioMod/releases
|
||||
|
||||
let res = syncRequest('GET', apiURL, {"headers":{"User-Agent":"Fuck you for requiring user agents!"}});
|
||||
let url = JSON.parse(res.getBody())[0].assets[0].browser_download_url;
|
||||
let name = JSON.parse(res.getBody())[0].assets[0].name;
|
||||
if(url) {
|
||||
console.log("Downloading " + url);
|
||||
let file = fs.createWriteStream(modDirectory + name);
|
||||
let bytesDownloaded = 0;
|
||||
let downloadStartTime = Date.now();
|
||||
https.get(url, function(response) {
|
||||
let bytesToDownload = response.headers['content-length'];
|
||||
response.pipe(file);
|
||||
response.on("data", chunk => {
|
||||
bytesDownloaded += chunk.length;
|
||||
let downloadTimeElapsed = Date.now() - downloadStartTime;
|
||||
let bytesPerSecond = bytesDownloaded / (downloadTimeElapsed/1000);
|
||||
let timeToComplete = Math.floor((bytesToDownload - bytesDownloaded)/bytesPerSecond);
|
||||
sLog("Downloading "+name+" "+(bytesDownloaded/bytesToDownload*100).toPrecision(3)+"% ("+formatBytes(bytesDownloaded)+" / "+formatBytes(bytesToDownload)+")\r\n"+
|
||||
"about "+timeToComplete+" seconds remaining ("+formatBytes(bytesPerSecond)+"/s)");
|
||||
}).on("end", x => {
|
||||
sLog.clear();
|
||||
console.log(" Downloaded in "+moment.utc(moment.duration(Date.now()-downloadStartTime).as('milliseconds')).format('mm:ss')); // because sLog.clear() doesn't seem to do the job of ending the line properly
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
} else {
|
||||
// treat it as a search and download the top result
|
||||
factorioAPI.init(false, modDirectory, "", config.factorio_version);
|
||||
factorioAPI.authenticate({
|
||||
username: config.username,
|
||||
token: config.token,
|
||||
require_ownership: false
|
||||
}).then(() => {
|
||||
factorioAPI.searchMods(term).then(body => {
|
||||
console.log(body)
|
||||
console.log("Im gonna download: "+body[0].name + " in version: " + body[0].latest_release.version);
|
||||
factorioAPI.downloadMod( {name: body[0].name, version: body[0].latest_release.version}).then(()=>{
|
||||
console.log("Mod downloaded");
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
} else {
|
||||
// treat it as a search and download the top result
|
||||
factorioAPI.init(false, modDirectory, "", config.factorio_version);
|
||||
factorioAPI.authenticate({
|
||||
username: config.username,
|
||||
token: config.token,
|
||||
require_ownership: false
|
||||
}).then(() => {
|
||||
factorioAPI.searchMods(term).then(body => {
|
||||
console.log("Im gonna download: "+body[0].name + " in version: " + body[0].latest_release.version);
|
||||
factorioAPI.downloadMod( {name: body[0].name, version: body[0].latest_release.version}).then(()=>{
|
||||
console.log("Mod downloaded");
|
||||
});
|
||||
});
|
||||
});
|
||||
reject(new Error("Invalid search term"));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
module.exports.removeMod = function removeMod(term, instance, force = false){
|
||||
if(instance == "shared"){ // modDirectory has to end in /
|
||||
var modDirectory = "sharedMods/";
|
||||
} else {
|
||||
var modDirectory = "instances/"+instance+"/instanceMods/";
|
||||
}
|
||||
if(term && typeof term == "string" && term.length > 0){
|
||||
let mods = fs.readdirSync(modDirectory);
|
||||
let modsMatchingFilter = mods.filter(mod => mod.toLowerCase().includes(term.toLowerCase()));
|
||||
if(modsMatchingFilter.length < 1){
|
||||
console.log("No mods found matching search");
|
||||
} else if(modsMatchingFilter.length == 1){
|
||||
console.log("Deleting "+modsMatchingFilter[0]);
|
||||
fs.unlinkSync(modDirectory+modsMatchingFilter[0]);
|
||||
console.log("Deleted.");
|
||||
} else if(modsMatchingFilter.length > 1){
|
||||
console.log("Found multiple mods, not doing anything");
|
||||
modsMatchingFilter.forEach(mod => console.log(mod));
|
||||
return new Promise((resolve, reject) => {
|
||||
if(instance == "shared"){ // modDirectory has to end in /
|
||||
var modDirectory = "sharedMods/";
|
||||
} else {
|
||||
var modDirectory = "instances/"+instance+"/instanceMods/";
|
||||
}
|
||||
}
|
||||
if(term && typeof term == "string" && term.length > 0){
|
||||
let mods = fs.readdirSync(modDirectory);
|
||||
let modsMatchingFilter = mods.filter(mod => mod.toLowerCase().includes(term.toLowerCase()));
|
||||
if(modsMatchingFilter.length < 1){
|
||||
console.log("No mods found matching search");
|
||||
} else if(modsMatchingFilter.length == 1){
|
||||
console.log("Deleting "+modsMatchingFilter[0]);
|
||||
fs.unlinkSync(modDirectory+modsMatchingFilter[0]);
|
||||
console.log("Deleted.");
|
||||
} else if(modsMatchingFilter.length > 1){
|
||||
console.log("Found multiple mods");
|
||||
modsMatchingFilter.forEach(mod => console.log(mod));
|
||||
if(query("Delete all mods matching filter?")){
|
||||
let modsToDelete = modsMatchingFilter.length;
|
||||
for(let i = 0; i < modsToDelete; i++){
|
||||
fs.unlinkSync(modDirectory+modsMatchingFilter[i]);
|
||||
console.log("Deleted "+modsMatchingFilter[i]);
|
||||
}
|
||||
} else console.log("Did not delete mods.")
|
||||
}
|
||||
resolve();
|
||||
} else {
|
||||
reject(new Error("Invalid search term"));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 'https://api.github.com/repos/Danielv123/factorioClusterioMod/releases'
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
"bcryptjs": "^2.4.3",
|
||||
"body-parser": "^1.18.2",
|
||||
"cache-require-paths": "^0.3.0",
|
||||
"cli-interact": "^0.1.9",
|
||||
"codecov": "^3.0.1",
|
||||
"compression": "^1.7.2",
|
||||
"deepmerge": "^1.5.2",
|
||||
@@ -56,6 +57,7 @@
|
||||
"request": "^2.83.0",
|
||||
"right-pad": "^1.0.1",
|
||||
"rmdir-sync": "^1.0.1",
|
||||
"sanitizer": "^0.1.3",
|
||||
"single-line-log": "^1.1.2",
|
||||
"socket.io": "^2.0.4",
|
||||
"socket.io-client": "^2.0.4",
|
||||
|
||||
@@ -22,4 +22,4 @@ module.exports = class remoteCommands {
|
||||
scriptOutput(data){
|
||||
// we don't return anything yet
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user