您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Shows members which aren't currently participating in an OC in the OC2.0 system, order by CE
// ==UserScript== // @name OC 2.0 MemberWatch // @namespace http://tampermonkey.net/ // @version 1.6.1 // @description Shows members which aren't currently participating in an OC in the OC2.0 system, order by CE // @author Allenone [2033011], Mr_Bob [479620] // @match https://www.torn.com/factions.php?step=your* // @icon https://www.google.com/s2/favicons?sz=64&domain=torn.com // @license MIT // ==/UserScript== (function() { 'use strict'; const API_KEY = ""; const INACTIVE_TIME_LIMIT = 3; // Days of inactivity to filter let isProcessing = false; let inactiveFilter = false; // Faction CrimeWatch Panel Creation const factionTabs = document.querySelector('.faction-tabs.ui-tabs-nav.ui-helper-reset.ui-helper-clearfix.ui-widget-header.ui-corner-all'); function createCrimeWatchPanel() { if (document.querySelector('#crimewatch')) return; const panelWrapper = document.createElement('div'); panelWrapper.id = 'crimewatch'; panelWrapper.className = 'border-round'; panelWrapper.setAttribute('role', 'heading'); panelWrapper.setAttribute('aria-level', '6'); // Add custom styling for panel const style = document.createElement('style'); style.innerHTML = ` .active.title-toggle .arrow { background-position: 0 0; border-left: 5px solid transparent; border-right: 5px solid transparent; border-top: 5px solid #999; margin-top: 13px; margin-right: 12px; } .active.title-toggle:hover .arrow { background-position: 0 -14px; border-left: 5px solid transparent; border-right: 5px solid transparent; border-top: 5px solid #ddd; border-top-color: var(--panel-divider-outer-side-color); margin-top: 13px; margin-right: 12px; } .title-toggle .arrow { background-position: -14px 0; border-left: 5px solid #999; border-bottom: 5px solid transparent; border-top: 5px solid transparent; margin-top: 10px; margin-right: 14px; } .title-toggle:hover .arrow { background-position: -14px -14px; border-left: 5px solid #ddd; border-left-color: var(--panel-divider-outer-side-color); margin-top: 10px; margin-right: 14px; } .arrow { height: 14px; width: 14px; float: right; margin-top: 8px; margin-right: 10px; background: url(/images/v2/forums/dropdown/arrows.png) 0 0 no-repeat; cursor: pointer; width: 0px; height: 0px; border-left: 5px solid transparent; border-right: 5px solid transparent; border-top: 5px solid #999; margin-top: 13px; } `; document.head.appendChild(style); const panelTitle = createPanelTitle(); const membersList = createMembersList(); panelWrapper.appendChild(panelTitle); panelWrapper.appendChild(membersList); if (factionTabs && factionTabs.parentNode) { factionTabs.parentNode.insertBefore(panelWrapper, factionTabs.nextSibling); } addPanelToggleFunctionality(panelWrapper); } // Create title for the panel function createPanelTitle() { const titleDiv = document.createElement('div'); titleDiv.className = 'border-round m-top10 title-black title-toggle active'; titleDiv.setAttribute('role', 'button'); titleDiv.setAttribute('aria-expanded', 'false'); titleDiv.innerHTML = ` <i class="arrow"></i> CrimeWatch `; return titleDiv; } // Create the members list function createMembersList() { const panelUl = document.createElement('ul'); panelUl.className = 'panel fm-list cont-gray bottom-round'; panelUl.style.display = 'block'; const listItem = document.createElement('li'); listItem.className = 'rating w2'; listItem.style.height = 'auto'; listItem.style.padding = '10px'; const membersUl = document.createElement('ul'); membersUl.style.display = 'grid'; membersUl.style.gridTemplateColumns = 'repeat(auto-fill, minmax(150px, 1fr))'; membersUl.style.gap = '10px'; membersUl.style.listStyleType = 'none'; membersUl.style.padding = '0'; membersUl.style.margin = '0'; listItem.appendChild(membersUl); panelUl.appendChild(listItem); return panelUl; } // Add the toggle functionality for the panel function addPanelToggleFunctionality(panelWrapper) { panelWrapper.addEventListener('click', function (event) { if (event.target.classList.contains('title-toggle')) { event.target.classList.toggle('active'); const nextElement = event.target.nextElementSibling; if (nextElement) { nextElement.style.display = nextElement.style.display === 'none' ? '' : 'none'; } } }); } // Fetch and process the member data async function loadMemberData() { if (isProcessing || document.querySelector('.wrapper')) return; isProcessing = true; const members = await getFilteredMembers(); const membersUl = document.querySelector('#crimewatch .rating ul'); // Clear and append new members in order of position membersUl.innerHTML = ''; // Sort members by position const sortedMembers = Object.entries(members).sort(([idA, { position: posA }], [idB, { position: posB }]) => posA - posB); // Append members in sorted order sortedMembers.forEach(([id, { name, position }]) => { const memberLi = createMemberListItem(id, { name, position }); membersUl.appendChild(memberLi); }); isProcessing = false; } // Create list item for each member function createMemberListItem(id, { name, position }) { const li = document.createElement('li'); li.style.padding = '8px'; li.style.border = '1px solid #ccc'; li.style.borderRadius = '6px'; li.style.textAlign = 'center'; li.style.color = 'inherit'; li.style.boxShadow = '0 1px 3px rgba(0, 0, 0, 0.1)'; li.style.transition = 'background-color 0.2s, box-shadow 0.2s'; // Hover effects const link = document.createElement('a'); link.href = `https://www.torn.com/profiles.php?XID=${id}`; link.textContent = `#${position}: [${id}] ${name}`; link.target = '_blank'; link.style.textDecoration = 'none'; link.style.color = 'inherit'; li.appendChild(link); return li; } async function getFilteredMembers() { try { const unixTimestamp = Math.floor(Date.now() / 1000); const excludedUserIDs = new Set(); // Fetch members list from faction const membersResponse = await fetch(`https://api.torn.com/v2/faction/members,crimes?key=${API_KEY}&cat=available&offset=0`); const membersData = await membersResponse.json(); // Fetch sorted member list based on crimeexp const crimeexpResponse = await fetch(`https://api.torn.com/faction/?selections=crimeexp&key=${API_KEY}`); const crimeexpData = await crimeexpResponse.json(); // Map crimeexp positions const crimeexpPositions = new Map(); crimeexpData.crimeexp.forEach((id, index) => { crimeexpPositions.set(id, index + 1); // Position starts from 1 }); // Filter members and assign positions from crimeexp const members = membersData.members.reduce((acc, member) => { if (member.position !== 'Recruit') { if (inactiveFilter) { if (unixTimestamp - member.last_action.timestamp <= (INACTIVE_TIME_LIMIT * 86400)) { // Get the crimeexp position for the member, default to "N/A" if not found const position = crimeexpPositions.get(member.id) || "N/A"; acc[member.id] = { name: member.name, position }; } } else { // Get the crimeexp position for the member, default to "N/A" if not found const position = crimeexpPositions.get(member.id) || "N/A"; acc[member.id] = { name: member.name, position }; } } return acc; }, {}); // Exclude users involved in crimes membersData.crimes.forEach(crime => { crime.slots.forEach(slot => { if (slot.user_id) excludedUserIDs.add(slot.user_id); }); }); // Return members excluding those involved in crimes return Object.fromEntries( Object.entries(members).filter(([userID]) => !excludedUserIDs.has(Number(userID))) ); } catch (error) { console.error("Error fetching member data", error); return {}; } } // Check if Crime tab is active, then initialize panel function checkFactionTab() { if (location.hash.includes('tab=crimes')) { createCrimeWatchPanel(); loadMemberData(); } } window.addEventListener('hashchange', checkFactionTab); checkFactionTab(); })();