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: Difference between revisions

From Soyjak Wiki, the free ensoyclopedia
Jump to navigationJump to search
Heckin' blanked!
Tag: Blanking
No edit summary
Line 1: Line 1:
(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 });
})();

Revision as of 00:59, 25 July 2026

(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 });

})();