nHentai SauceBot

Automatically converts every 5-6 digit number it finds into a link to nHentai

// ==UserScript==
// @name         nHentai SauceBot
// @namespace    http://tampermonkey.net/
// @version      0.2
// @description  Automatically converts every 5-6 digit number it finds into a link to nHentai
// @author       ProgrammingandPorn
// @match        *://*.reddit.com/*
// @grant        none
// @icon         data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABHNCSVQICAgIfAhkiAAABKpJREFUWIXFl09oVFcUxn/3vjfzZjqNE20Qg6YDSdFCmkhLdBVEgsZaQZFYXWgp1BYE20WzcFMXXWbRYhcN+UMWLbalNaVQYimEEl2UYiFIQyQYY2owOtXmzTROMpk/7717u5g4ScwYX2ywBx68e+ae833z3XMO7wrmzTTNqrKysvdDoVCzaZrVUsrnAcnamKuUmnNddzybzfbPzMy0u647CSAAwuHw6xUVFd9JKdetEeCKppR6YNv20Uwm0y9M06yqrKy89qzAF5GYjsfjdUY0Gv0oFAo1PUtwACFESGudM0OhUDOA1ho084cCQog1BdRaz78UMIQQhMPhvaZhGNVW3uMN+QKt4WqkgD/dNJedJJfdJONGHkzj6VBdjxovyG5zA7sDG6g2IygNn2bG+Vkl8QzjJRGLxRzABDAcj/bgNhqs9cUcjvLoyUzypXcPN+iPiJn3eNvYxLvhKgJyIeb3XJIP8jdQAeOhKo6IxWL6UdY/WHW8GIgsceeUx5GZq/xlrQxemYPvy17DkkvJTjhpjuSGH1VTLe9z0+D03Mgy9+dzt4gH1MroQDyg6MhMLPF5ShVyljjKkoMmHtQM51PF9aXsFN/IBEI+eS4JKTkvbC5lp4q+YXeGe0Fdcn/JjEIIurK3i+u23C1f4ItJtOVuFdfd2duP7arHZh3Vc8X3pPR8g5eKWZzLN4GMWDjvTcpcNYHFMRlRWv4VCazTCwXTE6mjLFcgJITg4MGD9Pb2Mjo6ytDQEB0dHTQ2NhaHzbqcoidSV4yP6se37/I2pDC1tuVN6o0y3gptYbMZxlOKTu5x+rcfqaioIJlMMjIygmVZ1NfXY1kWN2/e5Nu9x3kvsAVDSu64Gb7K3uEPb4axoFuqDlRJAkt2eB4fis0cD28h8dlptjbv4tSpU/T39xcTCiHo7Oxk3759/PpJFy/3/ML5uUnO6TjSWLF4S8yBR0waBud0nJ+yf7O1eRfAEvCHirW2tjI+Ps7d9RYDGdsPeIH8kxR4aJ7ncf36dSKRCC0tLQwODi4jAQU1lFJIf22rjPLy8o/97JRSkkqlaGpq4tixY+zfv598Po9t28zOziKEWHIkPk37VgBAKcXJkyc5e/YshrFQ2Y7jcOHCBbq7u5mYmFgNgScXYSkTQlBbW8vhw4dpaWmhvLy8+FtHRwdtbW1+STwdgcWmtSYajXLixAnOnDkDQENDA7Zt+yLge8AbhsGOHTvYuXPnEr8QglQqRXt7OwMDAwDU1NT4/gO+Z6xlWfT29pJOp6mtrS25JxgMApBIJHwT8K1AOp2mr6+PSCRCV1cXoVAIrXXxOXToEI2Njdy/f5+xsTHfBEQsFnMBX99aUkr6+vqKCqRSKdLpNBs3bsQwDGzbZs+ePUxPT/sC11rnRVVV1YPV3Am01mzfvp0DBw5QV1dHIBBgdHSUixcvcuXKFb9pgMLdQFRWVl4NBoOvripyjSyfzw/KbDbb/3+AAyy+mg1LKaPPEnz+avaKdF130rbto0opf5WzNuD/TE1Nvel53l0DwHXd8XQ6/bXWOielDAshngOkKMxT/V8frbWrtZ5xHOfa7OzsF4lE4h3HcYYA/gUeRwxt5UumGgAAAABJRU5ErkJggg==
// ==/UserScript==

(function() {
    'use strict';

    const MutationObserver = window.MutationObserver || window.WebKitMutationObserver;

    // Create a new MutationObserver object that will call its function on DOM modifications
    var observer = new MutationObserver(function(mutations, observer) {
        findNodes();
    });

    // Define what element should be observed by the observer
    // and what types of mutations trigger the callback
    observer.observe(document.body, {
        subtree: true,
        childList: true,
        attributes: true
    });

    // Call the initial findNodes function
    findNodes();

    // Parse each node individually, searching for either 5 or 6 consecutive digits.
    function handleNode(node) {
        let splits = node.textContent.split(/(\d{6}|\d{5})/g);

        // If at least one match is found, create a span element to replace the text
        if (splits.length > 1) {
            let newSpan = document.createElement('span');

            // Loop through all matches
            splits.forEach(function(el) {
                let match = el.match(/\d{6}|\d{5}/g);

                // If it's a sauce, replace it with a link, otherwise, add the text as normal
                if (match && match.length == 1 && match[0] == el) {
                    let link = document.createElement('a');
                    link.textContent = el;
                    link.setAttribute('href', `https://nhentai.net/g/${el}/`);
                    link.setAttribute('target', '_blank');
                    link.classList.add('sauced');
                    link.style.color = "var(--newCommunityTheme-linkText)";
                    link.style.textDecoration = "underline";
                    newSpan.appendChild(link);
                } else {
                    newSpan.appendChild(document.createTextNode(el));
                }
            });

            // Finally replace the original child
            node.parentNode.replaceChild(newSpan, node);
        }
    }

    // Walk the DOM of the <body> handling all non-empty text nodes
    function findNodes() {
        //Create the TreeWalker
        let treeWalker = document.createTreeWalker(document.body, NodeFilter.SHOW_TEXT, {
            acceptNode: function(node) {
                if (node.textContent.length === 0 ||
                    node.nodeName !== '#text' ||
                    node.parentNode.nodeName == 'SCRIPT' ||
                    node.parentNode.nodeName == 'STYLE' ||
                    node.parentNode.nodeName == 'NOSCRIPT' ||
                    node.parentNode.className == 'sauced' ||
                    node.parentNode.closest('a') != null ||
		    node.parentNode.closest('[role="textbox"]') != null
                ) {
                    return NodeFilter.FILTER_SKIP; //Skip empty text nodes
                } else {
                    return NodeFilter.FILTER_ACCEPT;
                }
            }
        }, false);

        let nodes = [];

        // Push all nodes into a list as the DOMwalker becomes invalid after completion
        while (treeWalker.nextNode()) {
            nodes.push(treeWalker.currentNode);
        }

        //Iterate over all text nodes, calling handleTextNode on each node in the list
        nodes.forEach(function(el) {
            handleNode(el);
        });
    }
})();