pwnwriter / haylxon

⚡ Blazing-fast tool to grab screenshots of your domain list right from terminal.
https://crates.io/crates/hxn
MIT License
384 stars 16 forks source link

A way to run arbitrary javascript on the page being screenshot #101

Closed andxyz closed 1 month ago

andxyz commented 1 month ago

Description

Previously in a different tool I would run it with something along the lines of

--js='window.setTimeout(function() {window.scrollTo(0,document.body.scrollHeight);}, 100);window.setTimeout(function() {window.scrollTo(0,0);}, 400)'

I know that js looks ugly. But, this way I could capture images that relied on scrolling past them to load. Lazy loading images make the page look empty when I capture with something like

hxn -b /Applications/Chromium.app/Contents/MacOS/Chromium --width 1440 --fullpage --url "$url"

Any thoughts on a workaround. Or adding this as a feature?

My thought is that, as a workaround, I could also write an extension for chromium that does this for me, and perhaps your program would end up autoloading my javascript extension on every webpage.

Related Documentation or Links

pwnwriter commented 1 month ago

Hey,

Thanks for bringing this up!

Lazy loading images make the page look empty.

As a temporary solution, you can try the --delay argument.

I'll investigate this further over the weekend. Your idea to actually run arbitrary javascript is interesting and might be a good approach. I'll keep you updated on any progress :3

pwnwriter commented 1 month ago

I've added a way to run arbitrary js inside the page. Can you clone from feat/js branch and test if that suits your case?

you can add your preferred js from --javascript option.

andxyz commented 1 month ago

Okay! I can try out that branch, thank you. Please don't spend too much more time. I've also been working on an approach that uses puppeteer/puppeteer.

By the way, I tried the --delay command. It didn't work, the images wait to lazy load until the viewport scrolls over them.

pwnwriter commented 1 month ago

No worries! I implemented it during my break. Could you test the branch and let me know. I'll merge it into the main branch to release the new version.

subash0302 commented 1 month ago

I can confirm that the javascript feature is working.

POC:

https://github.com/pwnwriter/haylxon/assets/75214012/ddc2f257-17de-4493-b699-764399444475

subash0302 commented 1 month ago

FYI: Here's the snippet of code to test out this feature.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Change Background Color via Console</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            text-align: center;
            margin-top: 50px;
        }
    </style>
</head>
<body>
    <h1>Change Background Color via Console</h1>
    <p>Open the browser console and use the <code>changeBackgroundColor(color)</code> function to change the background color.</p>

    <script>
        function changeBackgroundColor(color) {
            document.body.style.backgroundColor = color;
        }
    </script>
</body>
</html>

You can change the color using : changeBackgroundColor('color');

pwnwriter commented 1 month ago

Thanks for confirming @subash0302 !

andxyz commented 1 month ago

@pwnwriter I ended up testing this out, thanks for merging into master.

Here was what worked for me on a page with lazy loading images

hxn --url 'https://www.urbanstrategies.com/projects/' --binary '/Applications/Chromium.app/Contents/MacOS/Chromium'  --delay 2 -x 1440 -y 5000 --javascript '!function(){async function e(e){return new Promise(n=>setTimeout(n,e))}function n(){(async()=>{console.log("hello from app"),scroll_max_height=Math.max(6e3,document.body.scrollHeight),scroll_jump_size=900,console.log(scroll_max_height),console.log(scroll_jump_size);for(let n=0;n<scroll_max_height;n+=scroll_jump_size)window.scrollTo(0,n),await e(600);window.scrollTo(0,0)})()}(function e(n){return n=n||0,new Promise(e=>e(chrome.runtime)).then(o=>o?Promise.resolve():n>3?Promise.reject("Failed waiting for chrome.runtime"):(n+=1,new Promise(e=>window.setTimeout(e,500)).then(()=>e(n))))})().then(n).catch(e=>{console.error(e),n()})}();'

I ended up having to:

urbanstrategies.com/projects page

The final command line is a tad long, but it works! Thanks for this! ❤️

Note:

I previously tried a custom chrome extension to run my custom js but it was hard to make work from the commandline. And my third attempt using a puppeteer script setup works, but is a bit too much to maintain for me.

In conclusion

This is a really nice solution. Thanks again for taking the time to add this feature

pwnwriter commented 1 month ago

Glad It worked!

This is a really nice solution. Thanks again for taking the time to add this feature

Always happy to help :D

knight-yagami commented 1 month ago

Amazing !