Last active
May 18, 2024 00:59
-
-
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.
This file contains 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
// 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