Greasy Fork is available in English.
Decode base64-encoded links in some pastebins and make URLs clickable
// ==UserScript==
// @name FMHY Base64 Auto Decoder
// @namespace http://tampermonkey.net/
// @version 3.2
// @description Decode base64-encoded links in some pastebins and make URLs clickable
// @author Mumukshu D.C
// @license MIT
// @match *://rentry.co/*
// @match *://rentry.org/*
// @match *://pastes.fmhy.net/*
// @match *://bin.disroot.org/?*#*
// @match *://privatebin.net/?*#*
// @match *://textbin.xyz/?*#*
// @match *://bin.idrix.fr/?*#*
// @match *://privatebin.rinuploads.org/?*#*
// @match *://pastebin.com/*
// @grant none
// @icon https://t1.gstatic.com/faviconV2?client=SOCIAL&type=FAVICON&fallback_opts=TYPE,SIZE,URL&url=http://fmhy.net&size=64
// ==/UserScript==
(function() {
'use strict';
const Utils = {
isBase64(str) {
return /^[A-Za-z0-9+/]+={0,2}$/.test(str);
},
decode(str) {
try {
return atob(str);
} catch {
return null;
}
},
isUrl(str) {
try {
return ['http:', 'https:', 'ftp:'].includes(new URL(str).protocol);
} catch {
return false;
}
},
escapeHTML(str) {
return str.replace(/[&<>"']/g, m => ({
'&': '&',
'<': '<',
'>': '>',
'"': '"',
"'": '''
})[m]);
},
linkify(text, style = '', target = '_blank') {
const escapedText = this.escapeHTML(text);
const urlPattern = /(https?:\/\/[^\s]+)/g;
return escapedText.replace(urlPattern, url =>
`<a href="${url}" target="${target}" style="${style}">${url}</a>`
);
}
};
console.assert(Utils.isUrl('https://fmhy.net') && !Utils.isUrl('javascript:alert(1)'), 'URL validation failed');
const HANDLERS = [
{
match: /^https:\/\/pastebin\.com\/.*/,
selector: '.de1',
process: (el) => {
const text = el.textContent.trim();
if (text.startsWith('aHR0')) {
const decoded = Utils.decode(text);
if (decoded) {
const originalColor = window.getComputedStyle(el).color;
el.innerHTML = Utils.linkify(decoded, `color: ${originalColor};`).replace(/\n/g, '<br>');
}
}
}
},
{
match: /rentry\.(co|org)|pastes\.fmhy\.net/,
selector: (url) => /^https:\/\/rentry\.(co|org)\/fmhybase64/i.test(url) ? 'code' : 'code, p',
process: (el) => {
const content = el.textContent.trim();
if (Utils.isBase64(content)) {
const decoded = Utils.decode(content)?.trim();
if (!decoded) return;
const lines = decoded.split('\n');
if (!lines.some(line => Utils.isUrl(line.trim()))) return;
el.innerHTML = lines.map(line => {
const trimmed = line.trim();
if (!Utils.isUrl(trimmed)) return Utils.escapeHTML(line);
const escaped = Utils.escapeHTML(trimmed);
return `<a href="${escaped}">${escaped}</a>`;
}).join('<br>');
}
}
},
{
match: /bin\.disroot\.org|privatebin\.net|textbin\.xyz|bin\.idrix\.fr|privatebin\.rinuploads\.org/,
selector: '#prettyprint',
process: (el) => {
const content = el.innerText.trim();
const lines = content.split('\n');
let modified = false;
const processedLines = lines.map(line => {
let target = line;
if (line.startsWith('`') && line.endsWith('`')) {
target = line.slice(1, -1);
}
if (Utils.isBase64(target)) {
const decoded = Utils.decode(target)?.trim();
if (decoded && Utils.isUrl(decoded)) {
modified = true;
const escaped = Utils.escapeHTML(decoded);
return `<a href="${escaped}">${escaped}</a>`;
}
}
return line;
});
if (modified) {
el.innerHTML = processedLines.join('\n');
}
}
}
];
const handler = HANDLERS.find(({ match }) => match.test(window.location.href));
if (!handler) return;
const processAll = () => {
const selector = typeof handler.selector === 'function'
? handler.selector(window.location.href)
: handler.selector;
document.querySelectorAll(selector).forEach(handler.process);
};
new MutationObserver(processAll).observe(document.body, { childList: true, subtree: true });
processAll();
})();