Copied from my GitHub techdiary

Hacking the web for fun and profit

Now a days javascript and HTML are the assembly language of the web (I first said this in 2012). While still stuff is fun, it’s very brittle because 1) the approach is brittle, and 2) everytime the code changes, which it will everything will break.

Script Injection

Bookmarklets

Turns out you can stick javascript in the address bar, that’s a bookmarklet. Here it is from the way back machine)

Grease Monkey - User Script loader

Called Taper Monkey for chrome, it auto loads a script when you enter a webpage. Useful to personalize websites via css and javascript.

I’m not sure the differences, but I use Voilent Monkey now.

Console Tricks

Load Jquery

You almost always want jquery to play

var jq = document.createElement('script');
jq.src = "https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js";
document.getElementsByTagName('head')[0].appendChild(jq);
// ... give time for script to load, then type (or see below for non wait option)
jQuery.noConflict();

Speed up video playback

document.querySelector("video").playbackRate = 1.25
document.querySelector("video").play()
document.querySelector("video").pause()

Debugging 101

Chrome Keyboard shortcuts

https://developers.google.com/web/tools/chrome-devtools/shortcuts

Key Command
C-S-I Enter dev tools
C-S-M Toggle Mobile Emulator
C-S-R Hard reload (breaking cache)
C-S-P Command Pallette (super cool)

Force reloading

Often needed for CSS -

  • A) C-S-R
  • Network Tab -> Disable caching

Capturing an object for later use

Often there’s a useful object, that’s only available in the closure. You can always assign a refernce on window e.g.

window.foo = foo_from_within_a_closure_found_from_debugging

Black boxing

Event Handlers

Real life examples

Download the Alexa sound recording

Goto page:

https://www.amazon.com/hz/mycd/myx/#/home/alexaPrivacy/activityHistory&custom&1388538769000&1587497019949

Turns out there are audio elements on the page

$("audio")

Normally, the src attribute in the src element would have a src element, which is does not:

<audio id="audio-A32DOYMUN6DTXA:1.0/2020/04/21/14/G090U61091621908/08:16::TNIH_2V.4f0562e5-aff9-48a1-868a-85aa77aac07aZXV/1">
    <source id="audioSource-A32DOYMUN6DTXA:1.0/2020/04/21/14/G090U61091621908/08:16::TNIH_2V.4f0562e5-aff9-48a1-868a-85aa77aac07aZXV/1"/>
</audio>

However, when you click on the play button src attribute appears on the source element:

<audio id="audio-A32DOYMUN6DTXA:1.0/2020/04/21/14/G090U61091621908/08:16::TNIH_2V.4f0562e5-aff9-48a1-868a-85aa77aac07aZXV/1">
    <source id="audioSource-A32DOYMUN6DTXA:1.0/2020/04/21/14/G090U61091621908/08:16::TNIH_2V.4f0562e5-aff9-48a1-868a-85aa77aac07aZXV/1"
    src="https://www.amazon.com/hz/mycd/playOption?id=A32DOYMUN6DTXA:1.0/2020/04/21/14/G090U61091621908/08:16::TNIH_2V.4f0562e5-aff9-48a1-868a-85aa77aac07aZXV/1">
</audio>

And luckily, the “src” is encoding in the audio source id. Let’s pull those out:

   https://www.amazon.com/hz/mycd/playOption?id=

So

$("audio source").each((i,e)=> console.log($(e).attr("id").replace("audioSource-","")))

And lets prepend the download URL

   https://www.amazon.com/hz/mycd/playOption?id=A3S5BH2HU6VAYF:1.0/2020/04/21/19/G090LF1175130LD2/23:09::TNIH_2V.252ac310-314c-48e4-b433-749bdb9e8b5eZXV/0

   <audio
   id="audio-A32DOYMUN6DTXA:1.0/2020/04/21/14/G090U61091621908/08:16::TNIH_2V.4f0562e5-aff9-48a1-868a-85aa77aac07aZXV/1"
   >
   <source
   id="audioSource-                                  A32DOYMUN6DTXA:1.0/2020/04/21/14/G090U61091621908/08:16::TNIH_2V.4f0562e5-aff9-48a1-868a-85aa77aac07aZXV/1"
   src="https://www.amazon.com/hz/mycd/playOption?id=A32DOYMUN6DTXA:1.0/2020/04/21/14/G090U61091621908/08:16::TNIH_2V.4f0562e5-aff9-48a1-868a-85aa77aac07aZXV/1"
   />
   </audio>

Putting it all together.

This is gobboldy gook for most folks, but useful for me to look up later:

let playerPrefix = "https://www.amazon.com/hz/mycd/playOption?id="
function dumpClips() {
    // For every  entry in the list
    $(".mainBox").each((i,e)=> {
        var audio_src =  $(e).find("audio source").attr("id").replace("audioSource-","");
        console.log(playerPrefix+audio_src);
        var timeLoc  =  $(e).find(".subInfo").get(0)
        if (timeLoc)
        {
            console.log(timeLoc.textContent.trim())
        }
        var textElem  =  $(e).find(".summaryCss").get(0)
        if (textElem)
        {
            var text = textElem.textContent.trim()
            console.log(text);
        }
        else
        {
            // console.log("Text not found", e)
        }
    })
}

function everyTick() {
    dumpClips()
    $("#nextButton").click()
}

setInterval(everyTick, 5*1000)

Red herrings - but good approaches

Red Herring: Look at source

You could go looking for the code, but don’t bother it’s minified and not required as you can easily execute the code, and interact with the results. However, if you want to chase this path

  1. Look at what code is downloaded from network and sources tab.
  2. Prettify source code
  3. Add breakpoints on source code, or DOM modification events, or callbacks like keyboard or mouse.

Red Herring: Play button doesn’t appear till you open the chevrons:

$(".fa-angle-down").click()

Red Herring: Audio src doesn’t appear till you click the play button:

$(".playButton").click()

Red Herring: Search for a handy JSON blob.

If you’re lucky the JS downlads a data blob, you can check this by going to the network view, and searching for what you’re looking for. In this case, a partial html page was downloaded, which is harder to parse then the DOM (which you can search via JQuery)

Automating todo item creation in omnifocus for web

Too painful - got into some react/redux sync model, gave up

Ominfocus doesn’t supprot APIs, so we need to automate the web.

In omnifocus, you can add a task by pressing the ‘c’ key, which brings up a dialog. We can “hook that”, by setting a breakpoing on global keypress events.

From there, we get into a closure that has an interesting object. Copy that to global scope.

Screen Size Previews

https://www.duplichecker.com/screen-resolution-simulator.php#

Open graph preview Facebook

https://developers.facebook.com/tools/debug/

Web Site Preview Debugger

https://metatags.io/

Fly out TOC

I started by trying to create this myself, but as with most “build” vs “buy”, you’re better off stealing and buying. Looks like this exists in:

CSS

Javscript Reverse Engineering Fly out TOC

Looks like the CSS needs to have the data setup correctly. I found some javascript to do this in hackmd, and started putzing with it. Looks like that gets me the DOM in the form I need.

CSS - Styling a web page low level abstraction.

CSS is stying for the web. CSS is very complex. I recommend using a higher level framework like Bootstrap in general, however abstractions are leaky so you also need to understand some core CSS concepts.

CSS selectors

I always forget these, but it matters as that’s how you select elements in jquery

A full summary, below are some I often use.

  • $(.class)
  • $(#id)
  • $(element) #e.g. h1

When nesting selectors here are the operators

  • space - decendant at any level
    • immediate decendant
      • Adjecent (e.g. sibling)
  • ~ - Not Adjecent (e.g. not sibling)

Bootstrap - A higher level abstraction over css.

If you’re using styles directly, you’re probably doing it wrong. Bootstrap is designed to handle different operations at different view ports, very helpful. For example, you can hide an element if you’re not on an extra large screen.

Other resources