Refactor out config injection in modManager

Change config in modManager to be passed to each individual functions
instead of requiring it be present at load time.
This commit is contained in:
Hornwitser committed 2019-09-16 16:04:08 +02:00
1 parent 5f33cf4d3b
commit a783bd9651
3 files changed
+244 -240

No files matched your search

+5 -7
View File
@@ -21,6 +21,7 @@ const objectOps = require("lib/objectOps.js");
const fileOps = require("lib/fileOps");
const stringUtils = require("lib/stringUtils.js");
const pluginManager = require("lib/manager/pluginManager");
const modManager = require("lib/manager/modManager");
const hashFile = require('lib/hash').hashFile;
// Uhm...
@@ -245,18 +246,15 @@ async function manage(config, instance) {
if (instance !== undefined) {
if(tool == "mods"){
(async function(){try{
// do require down here to reduce master load time
const modManager = require("lib/manager/modManager.js")(config);
// allow managing mods
if(action == "list"){
console.log(await modManager.listMods(instance));
console.log(await modManager.listMods(config, instance));
} else if(action == "search"){
console.log(await modManager.findMods(process.argv[6]));
console.log(await modManager.findMods(config, process.argv[6]));
} else if(action == "add" || action == "download"){
await modManager.addMod(process.argv[6], instance);
await modManager.addMod(config, process.argv[6], instance);
} else if(action == "remove" || action == "rm" || action == "delete"){
await modManager.removeMod(process.argv[6], instance);
await modManager.removeMod(config, process.argv[6], instance);
} else {
usage(instance, tool);
}
+237 -231
View File
@@ -14,7 +14,6 @@ const query = require('cli-interact').getYesNo;
const path = require("path");
const fileOps = require("lib/fileOps");
// const config = require("./../../config");
function ellipse(str, max){
@@ -24,255 +23,262 @@ function ellipse(str, max){
function formatBytes(a,b){if(0==a)return"0 Bytes";var c=1024,d=b||2,e=["Bytes","KB","MB","GB","TB","PB","EB","ZB","YB"],f=Math.floor(Math.log(a)/Math.log(c));return parseFloat((a/Math.pow(c,f)).toFixed(d))+" "+e[f]};
module.exports = function(config){
if(!config) config = require("./../../config");
const instances = require("./../getInstances.js")(config).sync();
return {
/**
Lists mods for an instance as a table. Warning, handles printing internally.
@param {Instance} instance - Instance object, see client.js
/**
Lists mods for an instance as a table. Warning, handles printing internally.
@param {Instance} instance - Instance object, see client.js
@example
var modManager = require("modManager")(config);
modManager.listMods(instance);
// console.logs table of mods installed on instance
// if instance.name is shared:
// console.logs mods located in /sharedMods as a nice table
*/
listMods: function(instance){
return new Promise((resolve, reject) => {
if (instances.includes(instance.name)) {
factorioAPI.init(false, instance.path("instanceMods"), instance.path("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();
});
} 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));
});
}
// get JSON data about GH releases
/*let res = syncRequest('GET', 'https://api.github.com/repos/Danielv123/factorioClusterioMod/releases', {"headers":{"User-Agent":"factorioClusterio"}});
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()))
*/
@example
var modManager = require("modManager");
modManager.listMods(config, instance);
// console.logs table of mods installed on instance
// if instance.name is shared:
// console.logs mods located in /sharedMods as a nice table
*/
async function listMods(config, instance) {
return new Promise((resolve, reject) => {
const instances = require("./../getInstances.js")(config).sync();
if (instances.includes(instance.name)) {
factorioAPI.init(false, instance.path("instanceMods"), instance.path("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();
});
},
/**
Searches mods.factorio.com for mods matching a search term and prints
the results to console as a neat looking table
} 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));
});
}
@param {string} searchTerm What to search for
// get JSON data about GH releases
/*let res = syncRequest('GET', 'https://api.github.com/repos/Danielv123/factorioClusterioMod/releases', {"headers":{"User-Agent":"factorioClusterio"}});
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()))
*/
findMods: function(searchTerm){
return new Promise((resolve, reject) => {
factorioAPI.init(false);
});
}
/**
Searches mods.factorio.com for mods matching a search term and prints
the results to console as a neat looking table
@param {string} searchTerm What to search for
*/
async function findMods(config, searchTerm) {
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));
});
});
}
async function addMod(config, term, instance) {
return new Promise((resolve, reject) => {
if (instance.name == "shared") {
var modDirectory = "sharedMods";
} else {
var modDirectory = instance.path("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(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);
}).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();
});
});
}).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));
});
});
},
addMod: function(term, instance){
return new Promise((resolve, reject) => {
if(instance.name == "shared") {
var modDirectory = "sharedMods";
} else {
var modDirectory = instance.path("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":"factorioClusterio"}});
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(path.join(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 {
reject(new Error("Invalid search term"));
}
});
},
removeMod: function removeMod(term, instance, force = false){
return new Promise((resolve, reject) => {
if(instance.name == "shared"){
var modDirectory = "sharedMods";
} else {
var modDirectory = instance.path("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(path.join(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(path.join(modDirectory, modsMatchingFilter[i]));
console.log("Deleted "+modsMatchingFilter[i]);
}
} else console.log("Did not delete mods.")
}
resolve();
} else {
reject(new Error("Invalid search term"));
}
});
},
} 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
// 'https://api.github.com/repos/Danielv123/factorioClusterioMod/releases'
/**
Download mod from github repo by looking for the first binary download in
the latest release, saving it to /sharedMods
@param {string} url a github repo URL, for example https://api.github.com/repos/Danielv123/factorioClusterioMod/releases. Must link to /releases
*/
downloadFromGitURL: function(url){
console.log("Downloading mod from "+url);
// get JSON data about releases
let res = syncRequest('GET', url, {"headers":{"User-Agent":"factorioClusterio"}});
let downloadUrl = 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()))
if(downloadUrl) {
console.log(downloadUrl);
let file = fs.createWriteStream("sharedMods/"+name);
https.get(downloadUrl, function(response) {
response.pipe(file);
console.log("Downloaded "+name);
let res = syncRequest('GET', apiURL, {"headers":{"User-Agent":"factorioClusterio"}});
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(path.join(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 {
reject(new Error("Invalid search term"));
}
});
}
async function removeMod(config, term, instance, force = false) {
return new Promise((resolve, reject) => {
if (instance.name == "shared") {
var modDirectory = "sharedMods";
} else {
var modDirectory = instance.path("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(path.join(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(path.join(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'
/**
Download mod from github repo by looking for the first binary download in
the latest release, saving it to /sharedMods
@param {string} url a github repo URL, for example https://api.github.com/repos/Danielv123/factorioClusterioMod/releases. Must link to /releases
*/
function downloadFromGitURL(url) {
console.log("Downloading mod from "+url);
// get JSON data about releases
let res = syncRequest('GET', url, {"headers":{"User-Agent":"factorioClusterio"}});
let downloadUrl = 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()))
if (downloadUrl) {
console.log(downloadUrl);
let file = fs.createWriteStream("sharedMods/"+name);
https.get(downloadUrl, function(response) {
response.pipe(file);
console.log("Downloaded "+name);
});
}
}
/*
module.exports.findUpdates = function(){
function findUpdates() {
console.log("Downloading mods...");
// get JSON data about releases
let res = syncRequest('GET', 'https://api.github.com/repos/Danielv123/factorioClusterioMod/releases', {"headers":{"User-Agent":"factorioClusterio"}});
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()))
}*/
}*/
module.exports = {
listMods,
findMods,
addMod,
removeMod,
downloadFromGitURL,
}
+2 -2
View File
@@ -10,7 +10,7 @@ module.exports = class remoteCommands {
this.config = mergedConfig;
this.socket = extras.socket;
const pluginManager = require("lib/manager/pluginManager.js");
// const modManager = require("lib/manager/modManager.js")(this.config);
// const modManager = require("lib/manager/modManager");
this.socket.on("hello", () => {
this.socket.emit("registerServerManager");
});
@@ -19,7 +19,7 @@ module.exports = class remoteCommands {
});
this.socket.on("serverManagerGetMods", async (data, callback) => {
// TODO: Implement this function separately from listMods (which console.logs it)
// let mods = modManager.getMods()
// let mods = modManager.getMods(this.config)
// callback(mods);
});
this.socket.on("serverManagerGetPlugins", async (data, callback) => {