Torn User ID Extractor

Replace status icon with checkbox and extract user IDs

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         Torn User ID Extractor
// @namespace    http://tampermonkey.net/
// @version      1.1
// @description  Replace status icon with checkbox and extract user IDs
// @match        https://www.torn.com/page.php?sid=UserList*
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        GM_setClipboard
// ==/UserScript==

(function() {
    'use strict';

    let cachedIDs = GM_getValue('cachedUserIDs', []);

    const HALLOWEEN_COLORS = {
        orange: '#ff6b1a',
        darkOrange: '#cc4c00',
        purple: '#6b1aff',
        darkPurple: '#4c00cc',
        green: '#1aff6b',
        black: '#333333',
    };

    function addCheckboxes() {
        // Find all status icons and replace them
        const statusIcons = document.querySelectorAll('.iconShow[title*="Offline"], .iconShow[title*="Online"], .iconShow[title*="Idle"]');
        statusIcons.forEach(icon => {
            if (!icon.parentElement.querySelector('.user-checkbox')) {
                // Create checkbox
                const checkbox = document.createElement('input');
                checkbox.type = 'checkbox';
                checkbox.checked = true;
                checkbox.className = 'user-checkbox';
                checkbox.style.cssText = `
                    cursor: pointer;
                    margin: 0;
                    vertical-align: middle;
                `;

                // Replace icon with checkbox
                icon.parentElement.replaceChild(checkbox, icon);
            }
        });
    }

    function extractUserIDs() {
        const userList = document.querySelector('.user-info-list-wrap.bottom-round.cont-gray');
        if (!userList) {
            console.log('User list not found');
            return;
        }

        const userItems = document.querySelectorAll('li[class*="user"]');
        const newIDs = Array.from(userItems)
            .filter(item => {
                const checkbox = item.querySelector('.user-checkbox');
                return checkbox && checkbox.checked;
            })
            .map(item => {
                const match = item.className.match(/user(\d+)/);
                return match ? match[1] : null;
            })
            .filter(id => id !== null);

        // Add new IDs to cache, avoiding duplicates and limiting to 100
        newIDs.forEach(id => {
            if (!cachedIDs.includes(id) && cachedIDs.length < 100) {
                cachedIDs.push(id);
            }
        });

        // Save updated cache
        GM_setValue('cachedUserIDs', cachedIDs);

        // Update counter
        updateCounter();

        // Create a floating message
        showMessage(`${newIDs.length} user IDs extracted. Total cached: ${cachedIDs.length}`);
    }

    function formatAndCopyIDs() {
        const formattedData = {
            target_backup: cachedIDs.slice(0, 100).map(id => ({
                id: parseInt(id),
                notes: "",
                notes_color: ""
            }))
        };

        const jsonString = JSON.stringify(formattedData);
        GM_setClipboard(jsonString);
        console.log('Formatted user data copied to clipboard:', jsonString);

        showMessage(`${formattedData.target_backup.length} user IDs formatted and copied to clipboard!`);
    }

    function showMessage(text) {
        const message = document.createElement('div');
        message.textContent = text;
        message.style.cssText = `
            position: fixed;
            top: 20px;
            right: 20px;
            background-color: ${HALLOWEEN_COLORS.purple};
            color: black;
            padding: 15px;
            border-radius: 5px;
            z-index: 9999;
            box-shadow: 0 0 10px ${HALLOWEEN_COLORS.orange};
            animation: glow 1s ease-in-out infinite alternate;
        `;

        // Add glow animation
        const style = document.createElement('style');
        style.textContent = `
            @keyframes glow {
                from {
                    box-shadow: 0 0 5px ${HALLOWEEN_COLORS.orange},
                               0 0 10px ${HALLOWEEN_COLORS.orange};
                }
                to {
                    box-shadow: 0 0 10px ${HALLOWEEN_COLORS.purple},
                               0 0 20px ${HALLOWEEN_COLORS.purple};
                }
            }
        `;
        document.head.appendChild(style);

        document.body.appendChild(message);
        setTimeout(() => {
            document.body.removeChild(message);
        }, 3000);
    }

    function updateCounter() {
        counterSpan.textContent = `${cachedIDs.length}/100`;
    }

    function clearCache() {
        cachedIDs = [];
        GM_setValue('cachedUserIDs', cachedIDs);
        updateCounter();
        showMessage("Cache cleared!");
    }

    // Create UI elements with consistent width
    const buttonContainer = document.createElement('div');
    buttonContainer.style.cssText = `
        position: fixed;
        top: 10px;
        right: 10px;
        z-index: 9999;
        display: flex;
        flex-direction: column;
        align-items: flex-end;
        gap: 10px;
    `;

    const baseButtonStyle = `
        padding: 10px;
        width: 200px;
        color: black;
        border: none;
        border-radius: 5px;
        cursor: pointer;
        font-weight: bold;
        transition: all 0.3s ease;
        text-align: center;
        text-shadow: 1px 1px 2px rgba(0,0,0,0.3);
        box-shadow: 0 2px 4px rgba(0,0,0,0.2);
    `;

    const extractButton = document.createElement('button');
    extractButton.textContent = 'Extract Selected User IDs';
    extractButton.style.cssText = `
        ${baseButtonStyle}
        background-color: ${HALLOWEEN_COLORS.orange};
    `;
    extractButton.addEventListener('mouseover', () => {
        extractButton.style.backgroundColor = HALLOWEEN_COLORS.darkOrange;
        extractButton.style.transform = 'translateY(-2px)';
    });
    extractButton.addEventListener('mouseout', () => {
        extractButton.style.backgroundColor = HALLOWEEN_COLORS.orange;
        extractButton.style.transform = 'translateY(0)';
    });
    extractButton.addEventListener('click', extractUserIDs);

    const copyButton = document.createElement('button');
    copyButton.textContent = 'Format and Copy IDs';
    copyButton.style.cssText = `
        ${baseButtonStyle}
        background-color: ${HALLOWEEN_COLORS.purple};
    `;
    copyButton.addEventListener('mouseover', () => {
        copyButton.style.backgroundColor = HALLOWEEN_COLORS.darkPurple;
        copyButton.style.transform = 'translateY(-2px)';
    });
    copyButton.addEventListener('mouseout', () => {
        copyButton.style.backgroundColor = HALLOWEEN_COLORS.purple;
        copyButton.style.transform = 'translateY(0)';
    });
    copyButton.addEventListener('click', formatAndCopyIDs);

    const clearButton = document.createElement('button');
    clearButton.textContent = 'Clear Cache';
    clearButton.style.cssText = `
        ${baseButtonStyle}
        background-color: ${HALLOWEEN_COLORS.green};
    `;
    clearButton.addEventListener('mouseover', () => {
        clearButton.style.backgroundColor = '#008c45';
        clearButton.style.transform = 'translateY(-2px)';
    });
    clearButton.addEventListener('mouseout', () => {
        clearButton.style.backgroundColor = HALLOWEEN_COLORS.green;
        clearButton.style.transform = 'translateY(0)';
    });
    clearButton.addEventListener('click', clearCache);

    const counterSpan = document.createElement('span');
    counterSpan.style.cssText = `
        width: 180px;
        color: white;
        background-color: ${HALLOWEEN_COLORS.black};
        padding: 10px;
        border-radius: 5px;
        text-align: center;
        font-weight: bold;
        box-shadow: 0 2px 4px rgba(0,0,0,0.2);
    `;
    updateCounter();

    buttonContainer.appendChild(extractButton);
    buttonContainer.appendChild(copyButton);
    buttonContainer.appendChild(clearButton);
    buttonContainer.appendChild(counterSpan);
    document.body.appendChild(buttonContainer);

    // Add Halloween style to checkboxes
    const checkboxStyle = document.createElement('style');
    checkboxStyle.textContent = `
        .user-checkbox {
            accent-color: ${HALLOWEEN_COLORS.orange} !important;
            width: 16px;
            height: 16px;
        }
        .user-checkbox:hover {
            transform: scale(1.1);
            transition: transform 0.2s ease;
        }
    `;
    document.head.appendChild(checkboxStyle);

    // Initial setup
    addCheckboxes();

    // Add mutation observer to handle dynamically loaded users
    const observer = new MutationObserver((mutations) => {
        mutations.forEach((mutation) => {
            if (mutation.addedNodes && mutation.addedNodes.length > 0) {
                addCheckboxes();
            }
        });
    });

    const userList = document.querySelector('.user-info-list-wrap.bottom-round.cont-gray');
    if (userList) {
        observer.observe(userList, { childList: true, subtree: true });
    }
})();