SHA1 Calculator

Adds the ability to handle hash validator for SHA1 files based on Script by Sak32009

目前為 2024-11-30 提交的版本,檢視 最新版本

// ==UserScript==
// @name             SHA1 Calculator
// @namespace   SWScripts
// @version          v1.0
// @description    Adds the ability to handle hash validator for SHA1 files based on Script by Sak32009
// @license          MIT
// @author           BN_LOS
// @match           https://steamdb.info/depot/*/?show_hashes
// @grant             none
// ==/UserScript==

(function() {
    'use strict';

    const styleTag = document.createElement('style');
    styleTag.innerHTML = `
    .modal {
        display: none;
    }
    .modal.show {
        display: flex;
    }
    .toast {
        position: fixed;
        top: 1rem;
        right: 1rem;
        background-color: #333;
        color: white;
        padding: 1rem;
        border-radius: 0.375rem;
        opacity: 0;
        transition: opacity 0.3s;
        z-index: 10000;
    }
    .toast.show {
        opacity: 1;
    }
    `;
    document.head.appendChild(styleTag);

    const fileInputHTML = `
    <input type="file" id="fileInput" class="hidden" accept=".sha1" />
    `;
    document.body.insertAdjacentHTML('beforeend', fileInputHTML);

    const table = document.querySelector('#DataTables_Table_0');
    const thead = table.querySelector('thead tr');
    if (thead) {
        const th = document.createElement('th');
        th.classList.add('dt-orderable', 'dt-orderable-asc');
        th.textContent = 'Hash Status';
        thead.appendChild(th);
    }

    const modalButton = document.createElement('button');
    modalButton.classList.add('btn', 'btn-outline', 'mb-4');
    modalButton.innerHTML = 'Load .SHA1';
    const dtSearchDiv = document.querySelector('.dt-search');
    if (dtSearchDiv) {
        dtSearchDiv.insertAdjacentElement('beforebegin', modalButton);
    }

    modalButton.addEventListener('click', () => {
        document.querySelector('#fileInput').click();
    });

    document.querySelector('#fileInput').addEventListener('change', handleFileUpload);

    let validHashes = [];
    let notFoundFiles = [];

    function handleFileUpload(event) {
        const file = event.target.files[0];
        if (file && file.name.endsWith('.sha1')) {
            const reader = new FileReader();
            reader.onload = function(e) {
                const fileContent = e.target.result;
                parseSHA1File(fileContent);
            };
            reader.readAsText(file);
        }
    }

    function parseSHA1File(content) {
        const lines = content.split('\n').map(line => line.trim()).filter(line => line);
        validHashes = lines.map(line => {
            const [hash, filename] = line.split(' *');
            return {
                fullHash: hash,
                filename: filename.replace(/[\\\/]/g, '/').trim(),
                startHash: hash.slice(0, 10),
                endHash: hash.slice(-10)
            };
        });

        updateTableStatus();
        updateDownloadButton();
    }

    function updateTableStatus() {
        const rows = table.querySelectorAll('tbody tr');
        rows.forEach(row => {
            const cells = row.querySelectorAll('td');
            if (cells.length >= 2) {
                const filename = cells[0].textContent.trim().replace(/[\\\/]/g, '/');
                const hashCode = cells[1].textContent.replace('***', '').trim();

                const newCell = document.createElement('td');
                newCell.classList.add('text-center');

                if (hashCode) {
                    const startHash = hashCode.slice(0, 10);
                    const endHash = hashCode.slice(-10);

                    const match = validHashes.find(entry =>
                        entry.filename === filename &&
                        entry.startHash === startHash &&
                        entry.endHash === endHash
                    );

                    if (match) {
                        newCell.textContent = 'Valid';
                        newCell.classList.add('text-green-500');
                    } else {
                        newCell.textContent = 'Invalid';
                        newCell.classList.add('text-red-500');
                    }
                } else {
                    if (filename) {
                        newCell.textContent = 'Folder';
                        newCell.classList.add('text-blue-500');
                    } else {
                        newCell.textContent = 'Not In SHA1';
                        newCell.classList.add('text-gray-500');
                        notFoundFiles.push(filename);
                    }
                }

                row.appendChild(newCell);
            }
        });
    }

    function updateDownloadButton() {
        const buttonContainer = document.getElementById('notFoundFilesContainer');
        if (!notFoundFiles.length) {
            if (buttonContainer) {
                buttonContainer.remove();
            }
        } else {
            if (!buttonContainer) {
                const container = document.createElement('div');
                container.id = 'notFoundFilesContainer';
                container.innerHTML = `<button class="btn btn-outline" id="downloadButton">Download Missing Files</button>`;
                document.body.appendChild(container);

                document.getElementById('downloadButton').addEventListener('click', downloadMissingFiles);
            }
        }
    }

    function downloadMissingFiles() {
        const blob = new Blob([notFoundFiles.join('\n')], { type: 'text/plain' });
        const url = URL.createObjectURL(blob);
        const a = document.createElement('a');
        a.href = url;
        a.download = 'missing_files.sha1';
        a.click();
        URL.revokeObjectURL(url);
    }

    function showToast(message) {
        const toast = document.createElement('div');
        toast.classList.add('toast');
        toast.innerHTML = `<div class="alert alert-info"><span>${message}</span></div>`;
        document.body.appendChild(toast);

        setTimeout(() => {
            toast.classList.add('show');
        }, 0);

        setTimeout(() => {
            toast.classList.remove('show');
            toast.remove();
        }, 3000);
    }

    window.addEventListener('load', () => {
        const selectElement = document.querySelector('select#dt-length-0');
        if (selectElement) {
            selectElement.value = '-1';
            const event = new Event('change');
            selectElement.dispatchEvent(event);
        }
    });

})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址