您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Show total working stats on profile company and faction pages
// ==UserScript== // @name Torn Workstats Viewer // @namespace http://tampermonkey.net/ // @version 100.0 // @description Show total working stats on profile company and faction pages // @match https://www.torn.com/profiles.php* // @match https://www.torn.com/joblist.php* // @match https://www.torn.com/factions.php* // @grant GM_xmlhttpRequest // @grant GM_getValue // @grant GM_setValue // @connect api.torn.com // @author aquagloop // @license MIT // ==/UserScript== (function () { 'use strict'; const STORAGE_KEY = 'tornApiKey'; const fetchWorkStats = (userId, apiKey) => { return new Promise((resolve, reject) => { GM_xmlhttpRequest({ method: 'GET', url: `https://api.torn.com/v2/user/${userId}/hof?key=${apiKey}`, headers: { Accept: 'application/json' }, onload: (response) => { try { const data = JSON.parse(response.responseText); if (data.error) { reject(data.error.error); } else { resolve(data.hof?.working_stats?.value || 0); } } catch (e) { reject('Failed to parse response'); } }, onerror: () => reject('Network error') }); }); }; const formatStats = (value) => { if (value >= 1000) { return Math.round(value / 100) / 10 + 'k'; } return value.toLocaleString(); }; const isMobileView = () => window.matchMedia("only screen and (max-width: 768px)").matches; const handleProfilePage = async (apiKey) => { const urlParams = new URLSearchParams(window.location.search); const userId = urlParams.get('XID'); if (!userId) return; try { const totalStats = await fetchWorkStats(userId, apiKey); const jobLi = Array.from(document.querySelectorAll('li')).find(li => { const span = li.querySelector('.user-information-section span.bold'); return span && span.textContent.trim() === 'Job'; }); if (jobLi) { const workstatsLi = document.createElement('li'); workstatsLi.innerHTML = `<div class="user-information-section"><span class="bold">Work Stats</span></div><div class="user-info-value"><span>${totalStats.toLocaleString()}</span></div>`; jobLi.parentNode.insertBefore(workstatsLi, jobLi.nextSibling); } } catch (error) { console.error('Workstats error on profile page:', error); } }; const handleCompanyPage = async (apiKey) => { const employeesList = document.querySelector('ul.employees-list'); if (!employeesList) return; const employeeItems = employeesList.querySelectorAll('li'); for (const item of employeeItems) { const userLink = item.querySelector('.employee a.user.name'); if (userLink) { const match = userLink.href.match(/XID=(\d+)/); const userId = match ? match[1] : null; if (userId) { try { const totalStats = await fetchWorkStats(userId, apiKey); if (isMobileView()) { const rankLi = item.querySelector('.rank'); if (rankLi) { const workStatsDiv = document.createElement('div'); workStatsDiv.style.cssText = 'padding: 5px 0 0 10px; font-weight: bold; font-size: 14px;'; workStatsDiv.textContent = `Work Stats: ${totalStats.toLocaleString()}`; rankLi.parentNode.insertBefore(workStatsDiv, rankLi.nextSibling); } } else { const rankLi = item.querySelector('.rank'); if (rankLi) { const formattedStats = formatStats(totalStats); const statsSpan = document.createElement('span'); statsSpan.style.marginLeft = '5px'; statsSpan.style.fontWeight = 'bold'; statsSpan.textContent = formattedStats; rankLi.appendChild(statsSpan); } } } catch (error) { console.error(`Error fetching work stats for user ${userId}:`, error); } } } } }; const handleFactionPage = async (apiKey) => { const membersList = document.querySelector('ul.table-body'); if (!membersList) return; const memberItems = membersList.querySelectorAll('li.table-row'); for (const item of memberItems) { const userLink = item.querySelector('a[href*="/profiles.php?XID="]'); if (userLink) { const match = userLink.href.match(/XID=(\d+)/); const userId = match ? match[1] : null; if (userId) { try { const totalStats = await fetchWorkStats(userId, apiKey); const positionCell = item.querySelector('.positionCol___WXhYA') || item.querySelector('.positionCol___Lk6E4'); if (positionCell) { const formattedStats = formatStats(totalStats); const statsSpan = document.createElement('span'); statsSpan.textContent = formattedStats; statsSpan.style.cssText = 'margin-left: 5px; font-weight: bold;'; positionCell.appendChild(statsSpan); } } catch (error) { console.error(`Error fetching work stats for user ${userId}:`, error); } } } } }; const main = async () => { let apiKey = await GM_getValue(STORAGE_KEY, null); if (!apiKey) { apiKey = prompt('Enter your Torn API key:'); if (!apiKey) { alert('No API key entered. Work stats will not be displayed.'); return; } await GM_setValue(STORAGE_KEY, apiKey); } try { await fetchWorkStats('1', apiKey); if (window.location.pathname.includes('profiles.php')) { await handleProfilePage(apiKey); } else if (window.location.pathname.includes('joblist.php')) { await handleCompanyPage(apiKey); } else if (window.location.pathname.includes('factions.php')) { await handleFactionPage(apiKey); } } catch (error) { console.error('API key validation error:', error); if (error === 'Incorrect key' || error === 2) { await GM_setValue(STORAGE_KEY, null); alert('Invalid API key. Reload the page to enter a new one.'); } else { alert(`Error: ${error}`); } } }; const observer = new MutationObserver((mutations, obs) => { if (document.querySelector('.profile-container') || document.querySelector('.employees-list') || document.querySelector('.members-list')) { main(); obs.disconnect(); } }); observer.observe(document.body, { childList: true, subtree: true }); })();