Created
August 23, 2017 08:21
-
-
Save Darker/14ed6e38641945af09e12a759d25c836 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
console.log("This script changes cached resources' path in GreaseMonkey addon folder to force refresh."); | |
console.log("Press any key to start adding files."); | |
/*process.stdin.setRawMode(true); | |
process.stdin.resume(); | |
process.stdin.on('data', ()=>{getFiles(updateLoop);}); */ | |
var fs=require("fs"); | |
var path = require("path"); | |
/*var prompt = require('prompt-sync'); | |
prompt.question = function(q) { | |
process.stdout.write(q+"\n"); | |
return this.prompt(); | |
} */ | |
const readline = require('readline'); | |
const rl = readline.createInterface({ | |
input: process.stdin, | |
output: process.stdout | |
}); | |
rl.choose = function(question, yes, no, thisArg) { | |
rl.question(question+" [y/n]", (a) => { | |
if(a.toLowerCase()=="y") | |
yes.apply(thisArg, params); | |
else | |
no.apply(thisArg, params); | |
}); | |
var params = removeArguments(arguments, 4); | |
} | |
function removeArguments(args, count) { | |
var a = []; | |
a.push.apply(a, args); | |
return a.splice(0, count); | |
} | |
function getFiles(callback) { | |
//process.stdin.setRawMode(false); | |
console.log("Input the reference files - if those change, cached will be reloaded."); | |
console.log("To terminate adding of files, enter \"*\" without the quotes."); | |
var files = []; | |
var looper = (path) => { | |
if(path=="*") { | |
rl.choose("Stop adding files?", | |
()=>{callback(files)}, | |
()=>{getFilePath(looper);} | |
); | |
return; | |
} | |
var file = new FileInfo(path); | |
addFile(files, file); | |
getFilePath(looper); | |
} | |
// First read files from arguments | |
var last = null; | |
process.argv.forEach(function (val, index) { | |
last = val; | |
if(index>1 && val!="+start") { | |
var file = new FileInfo(val); | |
addFile(files, file); | |
} | |
}); | |
// Now, if needed, read files from stdin | |
if(last!="+start") | |
getFilePath(looper); | |
else | |
callback(files); | |
//callback(files); | |
} | |
function getFilePath(cb) { | |
rl.question('Filename: ', (path) => { | |
cb(path); | |
}); | |
} | |
function addFile(files, file) { | |
if(!file.exists) { | |
console.log("File "+file.path+" does not exist."); | |
} | |
//else if(files.indexOf(file)!=-1) | |
// console.log("File "+file.path+" already added."); | |
else { | |
console.log("+ "+file.path+""); | |
files.push(file); | |
} | |
} | |
function updateLoop(files) { | |
if(files.length<1) | |
throw new Error("Not enough files specified."); | |
console.log("Finding occurences of those files."); | |
var userscripts = findUserscripts(process.env.appdata+"\\Mozilla\\Firefox\\Profiles\\ap7ptx7o.default\\gm_scripts"); | |
//console.log("List of userscripts: ", userscripts); | |
userscripts.forEach( (userscript) => { | |
console.log("Checking "+userscript); | |
findOccurences(userscript, files); | |
}); | |
console.log("Started waiting for changes."); | |
setInterval(checkFiles, 500, files); | |
} | |
function checkFiles(files) { | |
files.forEach((file) => { | |
if(file.changed()) { | |
console.log(file.path+" changed."); | |
file.update(); | |
} | |
}); | |
} | |
function findUserscripts(p, scripts) { | |
// if provided, use existing array | |
var userscripts = scripts || []; | |
if (!fs.existsSync(p)){ | |
console.log("Directory does not exist:", p); | |
return; | |
} | |
var files = fs.readdirSync(p); | |
for(var i=0;i<files.length;i++) { | |
var filename=path.join(p, files[i]); | |
var stat = fs.lstatSync(filename); | |
if (stat.isDirectory()){ | |
findUserscripts(filename, userscripts); //recurse | |
} | |
else if (/\.user\.js$/i.test(filename)) | |
userscripts.push(filename); | |
}; | |
return userscripts; | |
} | |
/** Finds occureces or resources in userscript **/ | |
function findOccurences(userscript, watchedFiles) { | |
//var filenamesescaped = watchedFiles.map((file)=>{return file.jsPathEscaped;}); | |
//var matcher = new RegExp("("+filenamesescaped.join("|")+")", "i"); | |
var data = fs.readFileSync(userscript, 'utf8'); | |
watchedFiles.forEach( (file) => { | |
if(data.indexOf(file.jsPath)!=-1) { | |
console.log("Occurence: "+file.path+" in "+userscript); | |
file.refferencingFiles.push(userscript); | |
} | |
}); | |
} | |
/** Represent the file of a resource | |
* if this file changes, all refferencing GM scripts will be updated. **/ | |
function FileInfo(p) { | |
this.path = p; | |
this.jsPath = "file:///"+path.normalize(p).replace(/\\/g, "/"); | |
this.jsPathEscaped = escapeRegexChars(this.jsPath); | |
if(!fs.existsSync(p)) { | |
this.exists = false; | |
return; | |
} | |
this.exists = true; | |
this.stat = fs.statSync(p); | |
this.updateTime(); | |
// List of files that refference this file and will need update | |
this.refferencingFiles = []; | |
} | |
FileInfo.prototype.changed = function() { | |
//console.log("Time diff: "+this.currentTime() +" - "+this.time + " = " + (this.currentTime()-this.time)); | |
return this.time!=this.currentTime(); | |
} | |
FileInfo.prototype.currentTime = function() { | |
return new Date(fs.statSync(this.path).mtime).getTime(); | |
} | |
FileInfo.prototype.updateTime = function() { | |
this.time = this.currentTime(); | |
} | |
FileInfo.prototype.update = function() { | |
this.refferencingFiles.forEach(function(file) { | |
updatePaths(file, this.jsPathEscaped); | |
}, this); | |
this.updateTime(); | |
} | |
// Adds random #XXXX to path to force update | |
// first argument is the file to be edited (userscript) | |
// Second argument is the path to be replaced | |
function updatePaths(filename, resourcepath, callback) { | |
fs.readFile(filename, 'utf8', function (err,data) { | |
if (err) { | |
return console.log(err); | |
} | |
//var correctPath = "file:///"+path.normalize(resourcepath).replace(/\\/g, "/"); | |
var regexstr = "^\\/\\/(\\s*)@(resource\\s+[a-z0-9_]+|require)(\\s+)("+resourcepath+")(#[^\n]*?)*?$"; | |
var result = data.replace(new RegExp(regexstr, "gmi"), '//$1@$2$3$4#'+Math.random()); | |
console.log("Replacing: ", regexstr); | |
fs.writeFile(filename, result, 'utf8', function (err) { | |
if(callback) { | |
if (err) | |
callback(err); | |
else | |
callback(); | |
} | |
}); | |
}); | |
} | |
function escapeRegexChars(s) { | |
return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'); | |
}; | |
// Start | |
getFiles(updateLoop); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment