Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save d1manson/acd6e60329c8d891d42d05b615973e7b to your computer and use it in GitHub Desktop.
Save d1manson/acd6e60329c8d891d42d05b615973e7b to your computer and use it in GitHub Desktop.
script to manually insert into the page to help find cancelations
/*
Go to https://driverpracticaltest.direct.gov.uk, and get to the
"Test time" section. Then, open the F12 developer console, and copy paste
all of the following code. If something breaks, then just refresh the page and
try again. You can modify the configuration below.
Currently date parsing is rather basic, we just get the day for a specific target month,
e.g. May 2016, and then check if that day (e.g. 23rd) is before or equal to the day you
requested. It's not hard to improve upon this but I haven't bothered.
When a match is found a sound is played every 5 seconds. No booking is made, although
you could add functionality to do this. When a match is found, you can type the command:
clearInterval(beeper)
into the console to stop the sound. I advice opening links in a new tab, rather than continuing
to interact with the page after running the script.
Make sure that the console is set to *not* pause on exceptions - this is the button to the left of
the "Async" toggle in the top-right of the console (you want it to be gray not blue).
USE AT YOUR OWN RISK!!!!
You cannot redirect the whole page and have the script re-inject itself, so instead we
create an iframe in the page and only redirect that. We display:none on all other content
within the main page's body, so all you see is the iframe and red warning notice that we
also add to the body.
Note that in Chrome's devtool settings there is an option to show the timestamps from each
console log event (it works retrospectively, i.e. if you left the page running for ages without
the setting turned on, you can still turn it on and see the timestamps).
*/
// configuration
date_regex = /(\d+) (May|June) 2016/g;
target_day_of_month = 31; // before or on this day
interval_mins = 15; // how often to check
sound_file_url = "http://www.soundjay.com/mechanical/sounds/camera-shutter-click-10.mp3"; // played every 5 seconds when match is found
// =======================================
inner = document.createElement('iframe');
inner.src = window.location + "";
inner.style.width = '100%';
inner.style.height = '100%';
document.body.parentElement.style.height = "100%";
document.body.style.height = "100%";
document.body.appendChild(inner);
warning = document.createElement('div');
warning.style.cssText = 'position: fixed; top: 10px; right:10px; background: red; display: inline-block;'
warning.textContent = "!!!CUSTOM SCRIPT IN PAGE!!!"
document.body.appendChild(warning);
document.title = 'SCRIPT RUNNING'
beep_el = document.createElement('audio');
beep_el.src = sound_file_url
el = document.body.firstChild
while(el && el !== inner){
el.style && (el.style.display = 'none');
el = el.nextSibling;
}
do_refresh = function(){
try{
let el_1 = inner.contentDocument.querySelector('#load-earlier-availability');
let el_2 = inner.contentDocument.querySelector('#date-chosen');
let href = (el_1 && el_1.href) || (el_2 && inner.src);
if(!href){
throw "not ready to refresh yet";
}
console.log("refreshing...");
inner.src = "about:blank";
setTimeout(function(){
inner.src = href;
setTimeout(parse_document, 500);
}, 300);
} catch(e){
setTimeout(do_refresh, 300);
}
};
var beeper;
iframe_failed_to_load = function(){
try{
let a = inner.contentDocument; // will throw an error if the iframe failed to load due to dropped network
return false;
} catch(e){
return true;
}
}
retry_iframe_load = function(){
setTimeout(function(){
if(iframe_failed_to_load()){
let href = inner.src;
inner.src = "about:blank";
inner.src = href;
}
setTimeout(parse_document, 500);
}, 10000); // note that this has to be long enough to give the iframe a chance to load when there is a connection
}
parse_document = function(){
try{
let els = inner.contentDocument.getElementsByClassName('slotDateTime');
if(!els.length){
throw "couldn't find slots";
}
console.log('parsing document');
for(let ii=0; ii<els.length; ii++) {
let text = els[ii].textContent;
let matches = date_regex.exec(text);
if(matches && matches[1] && parseInt(matches[1]) <= target_day_of_month){
console.log("found match");
console.log('to stop sound, type: clearInterval(beeper)');
document.title = 'MATCH FOUND!!';
beep_el.play();
beeper = setInterval(beep_el.play.bind(beep_el), 1000*5);
return;
}
}
setTimeout(do_refresh, 1000 * 60 * interval_mins)
}catch(e){
if(iframe_failed_to_load()){
console.log("retry connection")
retry_iframe_load();
} else {
console.log("retry parse")
setTimeout(parse_document, 500);
}
}
}
setTimeout(parse_document, 300);
// hack to disable refresh timeout, by throwing error before window.location.href is set
// see the last script tag at the end of head in the page.
// a clever way of dealing with the timeout problem might be to use a different page as the parent,
// either a brand new page (which might not be permitted) or else the timeout landing page itself, since
// that doesn't have a timeout running!
String.prototype.toUpperCase = function(){
// I did originally use (new Error).stack, to try and check we are inside the specific timeout, but
// I kept failing to match for some reason..and it took too long to debug, so I just gave up and just
// settled for always throwing, since it seems like the only time this function is used is inside the
// timeout.
throw "I suspect you are trying to redirect on a page timeout. DON'T!!";
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment