CURRENT MISSION: Conclude the 2026 soyjak.party hack page, aswell as any pages relating to it, such as the Summer 2026 Crisis page.
Update Quotecord with any relevant info. See the blackboard for more info.
User:Tar/common.js
From Soyjak Wiki, the free ensoyclopedia
< User:Tar
Note: After publishing, you may have to bypass your browser's cache to see the changes.
- Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
- Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
- Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5.
(function () {
'use strict';
function isOnFilePage() {
const path = location.pathname;
const params = new URLSearchParams(location.search);
return (
/^\/File:/.test(path) ||
/^\/Special:Moderation/i.test(path) ||
/^\/Special:Moderation/i.test(path) ||
(
params.get("title") === "Special:Moderation" &&
params.get("modaction") === "show"
)
);
}
function extractImageData(img, callback) {
const tmpImg = new Image();
tmpImg.crossOrigin = 'anonymous';
tmpImg.onload = function () {
const canvas = document.createElement('canvas');
canvas.width = tmpImg.width;
canvas.height = tmpImg.height;
const ctx = canvas.getContext('2d');
ctx.drawImage(tmpImg, 0, 0);
callback(ctx, canvas);
};
tmpImg.src = img.dataset.originalSrc;
}
function revealLSB(imageData, bits) {
const data = imageData.data;
const maskShift = 8 - bits;
for (let i = 0; i < data.length; i += 4) {
data[i] = (data[i] << maskShift) & 0xff;
data[i + 1] = (data[i + 1] << maskShift) & 0xff;
data[i + 2] = (data[i + 2] << maskShift) & 0xff;
}
}
function decodeLSB(imageData, maxChars = 5000) {
const pixels = imageData.data;
const bits = [];
for (let i = 0; i < pixels.length; i += 4) {
bits.push(pixels[i] & 1, pixels[i + 1] & 1, pixels[i + 2] & 1);
}
let output = '';
for (let i = 0; i + 7 < bits.length && output.length < maxChars; i += 8) {
let c = 0;
for (let j = 0; j < 8; j++) c = (c << 1) | bits[i + j];
if (c === 0) break;
output += String.fromCharCode(c);
}
return output;
}
function addStegUIForImg(img) {
if (!img || img.dataset.stegscanInit) return;
img.dataset.stegscanInit = '1';
img.dataset.originalSrc = img.dataset.originalSrc || img.src;
const container = document.createElement('div');
Object.assign(container.style, {
margin: '6px 0 12px',
display: 'block',
maxWidth: img.width ? img.width + 'px' : '422px'
});
const label = document.createElement('div');
label.textContent = 'Steganography Scan:';
Object.assign(label.style, {
fontSize: '12px',
fontWeight: '600',
marginBottom: '4px'
});
const slider = document.createElement('input');
Object.assign(slider, { type: 'range', min: 1, max: 8, value: 1 });
slider.style.width = '99%';
const buttonWrapper = document.createElement('div');
Object.assign(buttonWrapper.style, {
display: 'flex',
justifyContent: 'center',
marginTop: '6px'
});
const decodeBtn = document.createElement('button');
decodeBtn.textContent = 'Decode';
Object.assign(decodeBtn.style, {
cursor: 'pointer',
padding: '4px 12px',
});
buttonWrapper.appendChild(decodeBtn);
container.appendChild(label);
container.appendChild(slider);
container.appendChild(buttonWrapper);
const parent = img.parentNode;
(parent.tagName.toLowerCase() === 'a' ? parent : img)
.insertAdjacentElement('afterend', container);
let lastBits = 1;
slider.addEventListener('input', () => {
const bits = Number(slider.value);
if (bits === lastBits) return;
lastBits = bits;
if (bits <= 1) {
img.src = img.dataset.originalSrc;
return;
}
extractImageData(img, (ctx, canvas) => {
const data = ctx.getImageData(0, 0, canvas.width, canvas.height);
revealLSB(data, bits - 1);
img.removeAttribute('srcset');
ctx.putImageData(data, 0, 0);
img.src = canvas.toDataURL();
});
});
decodeBtn.addEventListener('click', () => {
decodeBtn.disabled = true;
decodeBtn.textContent = 'Decoding...';
extractImageData(img, (ctx, canvas) => {
const data = ctx.getImageData(0, 0, canvas.width, canvas.height);
const message = decodeLSB(data);
decodeBtn.textContent = 'Decode';
decodeBtn.disabled = false;
if (message) {
navigator.clipboard.writeText(message)
.then(() => alert('Decoded message copied to clipboard'))
.catch(() => prompt('Decoded message:', message));
} else {
alert('No message detected.');
}
});
});
}
function scanAllImages() {
if (!isOnFilePage()) return; // Only run on File pages or media viewer
const content = document.querySelector('#content');
if (!content) return;
content.querySelectorAll('img').forEach(img => {
// Skip file history thumbnails
if (img.closest('.filehistory')) return;
addStegUIForImg(img);
});
}
scanAllImages();
const observer = new MutationObserver(() => {
if (isOnFilePage()) scanAllImages();
else observer.disconnect();
});
observer.observe(document.body, { childList: true, subtree: true });
})();