Skip to content

Instantly share code, notes, and snippets.

@stellarpower
Last active May 18, 2024 00:59
Show Gist options
  • Save stellarpower/0e1600b78bb7e478ab9679f5c8213f41 to your computer and use it in GitHub Desktop.
Save stellarpower/0e1600b78bb7e478ab9679f5c8213f41 to your computer and use it in GitHub Desktop.
Javascript is rather nasty. And there are loads of examples online that don't quite do what you need. Do everything once, document it, hopefully get it right, and re-use it.
// Demped from usecase script. Tidy-up to follow.
// To include this fromn Greasemonkey
// @require https://gist.githubusercontent.com/stellarpower/0e1600b78bb7e478ab9679f5c8213f41/raw/04fdf048d7870e5f655140cc4c4a08a59aaf9b8a/JavascriptDoneOnce.js
const ThisScript = "...";
function log(args){
const DEBUG = false;
if (DEBUG)
alert(args);
console.log(ThisScript + " :: " + args); // This may need t be expanded properly to string.
}
// Insert a script node into a webpage (e.g. from Greasemonkey)
// One way to ensure that somehting is defined in the page's scope.
// May need to be careful regarding document.ready / page load / etc. to make sure that the target definition sticks.
// Source: TODO - add me
// Must be defined using the function keyword like this for injection to work
// async function targetToInsert(...args){...}
// If it's a lambda, or a constant, or similar, then the *body* of the definition is what is injected
// Use like this:
// addJS_Node(myFunction)
// If oyu use an anonymous function, that code will just be executed bare, so use it to inject at the top level.
function addJS_Node (text, s_URL, funcToRun, runOnLoad) {
var D = document;
var scriptNode = D.createElement ('script');
if (runOnLoad) {
scriptNode.addEventListener ("load", runOnLoad, false);
}
scriptNode.type = "text/javascript";
if (text) scriptNode.textContent = text;
if (s_URL) scriptNode.src = s_URL;
if (funcToRun) scriptNode.textContent = '(' + funcToRun.toString() + ')()';
//scriptNode.setAttribute("grep", "Find me");
var targ = D.getElementsByTagName ('head')[0] || D.body || D.documentElement;
targ.appendChild (scriptNode);
}
// We can't just modify, we have to copy-constuct, using the original and any modifications we want to provide over.
function cloneRequest(original, newBody){
// We consumed the body, so we needed ot clone at higher scope.
var newRequest = new Request(original, {
//headers: { From: "[email protected]" },
body: JSON.stringify(newBody) // Don't forget to encode here
});
return newRequest;
}
// Have a list of functions that act as filters.
//Filter, and alternative function to transform it.
// Must be defined like this for injection to work
async function fetchNew(...args) {
// Always fall bakc to the handler below.
try {
// Filter for these URLs only
if (typeof(args[0]) == "string")
return await origFetch(...args);
if (args[0].url.toString() != SOME_TARGET_URL)
return await origFetch(...args);
log("fetchNew"); // Need to export log in main.
log("fetchNew called with args:", args);
// We mustn't consume the body in order to modify it - need t oclone here
console.log("-------------------");
var body = await args[0].clone()
//.text();
.json(); // Should be okay for Use case
// Edit the body here
newRequest = cloneRequest(args[0], body)
const response = await origFetch(newRequest);
//alert(args[0].body);
/*
* //work with the cloned response in a separate promise
* // chain -- could use the same chain with `await`.
* response
* .clone()
* .json()
* .then(body => console.log("intercepted response:", body))
* .catch(err => console.error(err))
* ;
*/
return response;
} catch(e){
console.error("fetchNew failed");
console.log(e);
console.error(...args);
// Don't really need ot log as there oculd be any number of reasons.
return await origFetch(...args)
}
};
async function sleepImplementation(ms){
return new Promise(function(r){
setTimeout(r, ms);
});
}
// You will *have* to await this in the calling scope
async function sleep(ms){
console.log("sleeping for " + ms + " ms");
await sleepImplementation(ms);
console.log("Slept " + ms + " ms");
}
function getElementByXpath(path) {
var result = document.evaluate(path, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
if (result === null)
console.log("Unalbe to find element with xpath " + path);
else
console.log("Found element with xpath " + path);
return result;
}
function addElementAtTop(element){
var container = document.getElementsByClassName("container")[0]
container.insertBefore(element, container.firstChild);
}
// Example of how to use a main function, for asynchronous use (can await in here)
$(document).ready(async function() {
// Do here as not working on the onclick button.
//window.open(window.location, '_blank');
//-------------------------
if(false){
window.fetch = fetchNew
fetch = fetchNew
unsafeWindow.fetch = fetchNew
}
//----------------------------
console.log("add nde")
addJS_Node (fetchNew); // will come out as `fetchNew` - so alias below.
//addJS_Node (origFetch); DO NOT DO THIS. Do it below instead.
addJS_Node (resetTime);
addJS_Node (cloneRequest);
addJS_Node (" \
origFetch = window.origFetch = fetch; \
fetch = window.fetch = fetchNew; \
"); // Runsin global scope
await main();
log("main finished");
// Repeatedly do this thing:
/*setInterval( function(){
* //d=new Date();
* //console.log(d.getTime());
* customButtonResetClickHandler();
*
},
2500
);
*/
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment