gabrielsroka/gabrielsroka.github.io

Thanks for the HN favorites export script!

cantino opened this issue · 2 comments

I modified it to do upvotes.

/* 
Export HN upvotes to CSV.

Setup:
Based on https://gabrielsroka.github.io/getHNFavorites.js

Copy this code to the browser console, or a bookmarklet, or, if using Chrome, to a Snippet. For example:
1. Press F12 (Windows) to open DevTools.
2. Go to Sources > Snippets, click New Snippet.
3. Give it a name, eg, "Export HN Upvotes".
5. Save (Ctrl+S, Windows).

Usage:
1. Navigate your browser to https://news.ycombinator.com/user?id=YOUR_USER_ID
2. Press F12 (Windows) to open DevTools.
3. Run the code. If using a Snippet, there's a Run button on the bottom right, or press Ctrl+Enter (Windows).
4. Look for the popup window in the upper-left corner of your browser.
*/

(function () {
    const popup = createPopup('HN Upvotes');
    const form = popup.appendChild(document.createElement('form'));
    form.innerHTML = '<button>Export</button>';
    form.onsubmit = async function (event) {
        event.preventDefault();
        const base = 'news.ycombinator.com';
        if (location.host != base || location.pathname != '/user') {
            popup.innerHTML = 'ERROR: Go to your user page and then try again.';
            return;
        }

        const id = location.search.split('=')[1];
        const url = `https://${base}/upvoted?id=${id}&p=`;
        
        const upvotes = [];
        for (var p = 1; true; p++) {
            popup.innerHTML = 'Exporting page ' + p + '...<br><br>';
            const response = await fetch(url + p);
            const html = await response.text();
            const parser = new DOMParser();
            const doc = parser.parseFromString(html, "text/html");
            const as = doc.querySelectorAll('a.storylink');
            as.forEach(a => upvotes.push(toCSV(a.innerText, a.href)));
            if (doc.querySelector('a.morelink') == null) break;
        }
        downloadCSV('Title,URL', upvotes, id + "'s HN upvotes");
        popup.innerHTML = 'Done.';
    };


    function createPopup(title) {
        const div = document.body.appendChild(document.createElement("div"));
        div.innerHTML = title + "<a onclick='document.body.removeChild(this.parentNode)' style='cursor: pointer; padding: 4px'>X</a><br><br>";
        div.style.position = "absolute";
        div.style.zIndex = "1000";
        div.style.left = "4px";
        div.style.top = "4px";
        div.style.backgroundColor = "white";
        div.style.border = '1px solid #ddd';
        return div.appendChild(document.createElement("div"));
    }
    function toCSV(...fields) {
        return fields.map(field => `"${field == undefined ? "" : field.toString().replace(/"/g, '""')}"`).join(',');
    }
    function downloadCSV(header, lines, filename) {
        const a = document.body.appendChild(document.createElement('a'));
        a.href = URL.createObjectURL(new Blob([header + "\n" + lines.join("\n")], {type: 'text/csv'}));
        const date = (new Date()).toISOString().replace(/T/, " ").replace(/:/g, "-").substr(0, 19);
        a.download = `${filename} ${date}.csv`;
        a.click();
    }
})();

hi @cantino

thanks for sharing. that's awesome!

since it's so similar to the other export, it might make sense to combine them, refactor out the common code, and change the "Export" button to ("Export Favorites" and "Export Upvoted"...)

if you're interested, feel free to create a PR

thanks.

hi @cantino

I'm going to close this for now. I've re-written some of the code above to support HTML. check out my latest version.

if you want to open a PR, feel free.

thanks