torn-crack

Simple Cracking Helper

Fra 03.08.2025. Se den seneste versjonen.

// ==UserScript==
// @name         torn-crack
// @namespace    torn-crack
// @version      0.0.1
// @description  Simple Cracking Helper
// @author       SirAua [3785905]
// @match        *://www.torn.com/page.php?sid=crimes*
// @grant        GM_xmlhttpRequest
// @grant        GM_addStyle
// @license      mit
// ==/UserScript==

(function () {
    'use strict';

    if (window.CRACK_INJECTED) {
        return;
    }
    window.CRACK_INJECTED = true;

    let debug = false;
    function crackLog(...args) {
        if (!debug) return;
        args.forEach((arg) => {
            console.log('[Crack] ' + arg)
        })
    }

    const PDA_API_KEY = '###PDA-APIKEY###';
    function isPDA() {
        const PDA_TEST_REGEX = !/^(###).+(###)$/.test(PDA_API_KEY);
        return PDA_TEST_REGEX;
    }

    crackLog('Userscript starts');

    const UPDATE_INTERVAL = 800; // ms
    const MAX_SUG = isPDA() ? 5 : 10;

    let dict = null;
    let dictLoaded = false;

    const wordlistUrl = 'https://raw.githubusercontent.com/danielmiessler/SecLists/refs/heads/master/Passwords/Common-Credentials/xato-net-10-million-passwords-1000000.txt';
    async function loadDict() {
        if (dictLoaded) return;
        crackLog('Loading wordlist...');
        GM_xmlhttpRequest({
            method: 'get',
            url: wordlistUrl,
            timeout: 30000,
            ontimeout: (error) => {
                crackLog('GET: Timeout', error);
                return;
            },
            onerror: (error) => {
                crackLog('GET Error:', error);
                return;
            },
            onload: (res) => {
                const txt = res.responseText;
                dict = txt.trim()
                    .split(/\r?\n/)
                    .map(w => w.trim().toUpperCase());
                dictLoaded = true;
                crackLog('Loaded', dict.length, 'words');
            },
        });
    }

    function patToReg(pat) {
        const standard = pat.toUpperCase().replace(/[*]/g, '.').trim();
        return new RegExp('^' + standard + '$');
    }

    function suggest(pat) {
        if (!dict) return [];
        const regex = patToReg(pat);
        const len = pat.length;
        let out = [];
        for (const word of dict) {
            if (word.length !== len) continue;
            if (!regex.test(word)) continue;
            out.push(word);
            if (out.length >= MAX_SUG) break;
        }
        return out;
    }

    function prependPanelToRow(row, pat) {
        const existing = row.querySelector('.__crackhelp_panel');
        if (existing) existing.remove();

        const panel = document.createElement('div');
        panel.className = '__crackhelp_panel';
        panel.style.cssText = `
      background: #000000ff;
      font-size: 9px;
      text-align: center;
      position: absolute;
      z-index: 9999;
    `;

        const listDiv = document.createElement('div');
        listDiv.style.cssText = 'margin-top: 2px;';
        panel.appendChild(listDiv);

        row.prepend(panel);

        async function updateSuggestions() {
            const sugs = suggest(pat);
            listDiv.innerHTML = '';
            sugs.forEach(w => {
                const sp = document.createElement('span');
                sp.style.cssText = 'padding:2px; color: #00ff00ff;';
                sp.textContent = w;
                listDiv.appendChild(sp);
            });
            if (sugs.length === 0) {
                const none = document.createElement('span');
                none.textContent = '(no matches)';
                none.style.color = '#a00';
                listDiv.appendChild(none);
            }
        }

        loadDict().then(updateSuggestions);
    }

    function scanOnce() {
        if (!location.href.endsWith('cracking')) return;

        const currentCrime = document.querySelector('[class^="currentCrime"]');
        if (!currentCrime) return;

        const container = currentCrime.querySelector('[class^="virtualList"]');
        if (!container) return;

        for (const crimeOption of container.getElementsByClassName('crimeOptionWrapper___IOnLO')) {
            let patText = '';
            for (const charSlot of crimeOption.getElementsByClassName('charSlot___b_S9h')) {
                if (!charSlot) return null;
                let char = charSlot.textContent.trim();
                if (char) {
                    patText += char.toUpperCase();
                } else {
                    patText += '*';
                }

            }
            prependPanelToRow(crimeOption, patText);
        }
    }

    // Initial and periodic scan
    scanOnce();
    setInterval(scanOnce, UPDATE_INTERVAL);

})();