Greasy Fork is available in English.
Convert HEX to text, in a post or comment on Facebook.
// ==UserScript==
// @name Facebook HEXtoTEXT
// @namespace https://github.com/holozok
// @description Convert HEX to text, in a post or comment on Facebook.
// @version 1.0.1
// @icon https://i.imgur.com/oz5CjJe.png
// @author holozok
// @ref Original author: lelinhtinh (baivong)
// @license MIT; https://baivong.mit-license.org/license.txt
// @match https://*.facebook.com/*
// @require https://greasemonkey.github.io/gm4-polyfill/gm4-polyfill.js?v=a834d46
// @run-at document-idle
// @grant GM.openInTab
// @grant GM_openInTab
// ==/UserScript==
/**
* If `false`, open in new tab after clicking on decoded link.
* @type {boolean} true or false
*/
const COPY_ONLY = false;
/**
* Makes the tab being opened inside a incognito mode/private mode window.
* Currently, only works with Tampermonkey BETA.
* @type {boolean} true or false
*/
const PRIVATE = true;
function validURL(url) {
try {
const uri = new URL(url);
return !!uri.host && uri.host.includes('.');
} catch (e) {
return false;
}
}
function cleanWordBreak(post) {
if (post.querySelector('.word_break') !== null) {
post.querySelectorAll('wbr').forEach((e) => e.remove());
post.querySelectorAll('span').forEach((span) => {
if (span.querySelector('span, img') !== null) return;
const text = document.createTextNode(span.textContent);
span.parentNode.replaceChild(text, span);
});
}
}
function renderResult(post, data) {
const { content, result } = data;
if (!content || !result) return;
post.innerHTML = post.innerHTML.replace(
content,
`
<strong
class="fb-hex${validURL(result) ? ' fb-hex-link' : ''}"
title="${COPY_ONLY ? '' : 'Click to open in new tab'}"
style="cursor:pointer"
>${result}</strong>
`,
);
}
function handle(post) {
if (post.querySelector('.fb-hex') !== null) return;
cleanWordBreak(post);
const handleURL = URL.createObjectURL(
new Blob(
[
'(',
function () {
self.onmessage = (e) => {
function hex2ascii(hex) {
if (!(typeof hex === 'number' || typeof hex == 'string')) return '';
hex = hex.toString().replace(/\s+/gi, '');
const stack = [];
for (let i = 0; i < hex.length; i += 2) {
const code = parseInt(hex.substr(i, 2), 16);
if (!isNaN(code) && code !== 0) {
stack.push(String.fromCharCode(code));
}
}
return stack.join('');
}
function getResult(content) {
content = content.match(/\b[a-f0-9\s]{12,}\b/i);
if (content === null) return {};
content = content[0].trim();
const result = hex2ascii(content);
return { content, result };
}
self.postMessage(getResult(e.data));
};
}.toString(),
')()',
],
{
type: 'application/javascript',
},
),
);
const worker = new Worker(handleURL);
worker.onmessage = (e) => {
if (!e.data) return;
renderResult(post, e.data);
};
worker.postMessage(post.textContent);
}
function getPost(e) {
let target = e.target;
if (target.closest('button, [role="button"], svg, path')) return;
let post = target;
let depth = 0;
while (post && depth < 20) {
const text = post.textContent || '';
if (text.length > 12 && /[a-f0-9\s]{12,}/i.test(text)) {
console.log('Found hex text in element:', post.tagName, text.substring(0, 50));
handle(post);
return;
}
post = post.parentElement;
depth++;
}
}
document.addEventListener('dblclick', getPost, true);
document.addEventListener('click', function(e) {
const target = e.target;
if (!target.textContent) return;
if (!window.clickCount) window.clickCount = 0;
if (!window.lastClickTime) window.lastClickTime = 0;
const now = Date.now();
if (now - window.lastClickTime > 300) {
window.clickCount = 0;
}
window.lastClickTime = now;
window.clickCount++;
if (window.clickCount >= 3) {
window.clickCount = 0;
getPost(e);
}
}, true);
function decodedClicking(e) {
const target = e.target;
if (!target.classList.contains('fb-hex')) return;
if (COPY_ONLY) return;
if (!target.classList.contains('fb-hex-link')) return;
const result = target.textContent;
GM.openInTab(result, {
active: true,
insert: true,
incognito: PRIVATE,
});
}
document.addEventListener('click', decodedClicking);