// ==UserScript==
// @namespace https://openuserjs.org/users/DanielBlaze
// @name Reddit Base64 Decoder
// @description Automatically base64 decode links in reddit posts
// @copyright 2018, DanielBlaze (https://openuserjs.org/users/DanielBlaze)
// @updateURL https://openuserjs.org/meta/DanielBlaze/Reddit_Base64_Decoder.meta.js
// @license MIT
// @version 2.0.0
// @author DanielBlaze
// @grant none
// @match https://*.reddit.com/r/*
// ==/UserScript==
// ==OpenUserJS==
// @author DanielBlaze
// ==/OpenUserJS==
/**
* Wraps HTML in some styling to show its been decoded
*/
function decodedBlock(inner) {
const css = [
'border: 1px dashed #e6e6e6',
'padding: 10px',
'background-image: linear-gradient(45deg, rgba(199,199,199,.25) 25%, rgba(227,227,227,.25) 25%, rgba(227,227,227,.25) 50%, rgba(199,199,199,.25) 50%, rgba(199,199,199,.25) 75%, rgba(227,227,227,.25) 75%, rgba(227,227,227,.25) 100%)',
'background-size: 40px 40px'
];
return `<div style='${css.join(';')}'>${inner}</div>`;
}
/**
* Attempts to decode an array of elements. Styling will be lost on any element which is decoded
* @param {HTMLElement[]} domElements
*/
function decode(domElements) {
// for all pararaph tags
domElements.forEach(domElement => {
// split on the words we find, and make sure we have something before continuing
const words = domElement.innerText.split(' ');
if (words.length === 0) return;
// decode the string
let changed = false;
const transformed = words.map(word => {
try {
const decoded = atob(word);
// if it's valid, change it
if (decoded.includes('https://') || decoded.includes('http://')) {
changed = true;
return decodedBlock(
decoded
.replace(/[\r\n]+/g, '<br /><br />')
.replace(/(https?:\/\/[^\s<]+)/g, `<a href="$1" style='text-decoration: underline #8989ff dotted; text-underline-offset: 2px;'>$1</a>`)
);
}
}
catch (_) {}
return word;
});
// only if we changed something should we update the HTML - otherwise we lose the original formatting
if (changed) domElement.innerHTML = transformed.join(' ');
});
}
(function () {
'use strict';
// check we have observers available to us
if (!MutationObserver) return;
// observer config - only interested in tree modifications
const config = {
childList: true,
subtree: true
};
// the callback to decode the string
const callback = function (mutationsList, observer) {
mutationsList.forEach(mutation => {
if (mutation.target.nodeName === 'DIV' && mutation.addedNodes.length > 0) {
// check we can find the post contents
const postContents = mutation.target.querySelectorAll('p');
if (!postContents) return;
// decode that bad boy
decode(postContents);
}
});
};
// create an observer instance with the callback
const observer = new MutationObserver(callback);
// Start observing the target node for mutations
observer.observe(document, config);
// run on page load incase no mutations occur, but only on old reddit
const postContainer = document.querySelector('.expando');
if (postContainer) {
const postContents = postContainer.querySelectorAll('p');
if (postContents) {
decode(postContents);
}
}
})();
Donate for the site OpenUserJS
Are you sure you want to go to an external site to donate a monetary value?
WARNING: Some countries laws may supersede the payment processors policy such as the GDPR and PayPal. While it is highly appreciated to donate, please check with your countries privacy and identity laws regarding privacy of information first. Use at your utmost discretion.