// ==UserScript== // @name Shared IP Manager // @namespace http://tampermonkey.net/ // @version 1.1.1 // @description Transform shared IP overlay into searchable table format // @author Ryahn // @match *://*/* // @grant none // ==/UserScript== (function() { 'use strict'; // Function to extract country code from flag class function getCountryCode(flagElement) { const classes = flagElement.className; const match = classes.match(/tck-provider-country-flag\s+(\w+)/); return match ? match[1].toUpperCase() : ''; } // Function to get country name from flag element function getCountryName(flagElement) { return flagElement.getAttribute('data-original-title') || ''; } // Function to get provider info function getProviderInfo(providerElement) { return { name: providerElement.textContent.trim(), asn: providerElement.getAttribute('data-original-title') || '' }; } // Function to get type info function getTypeInfo(typeElement) { return typeElement.getAttribute('data-original-title') || ''; } // Function to extract usage count function getUsageCount(usageText) { const match = usageText.match(/(\d+)\s+time/); return match ? parseInt(match[1]) : 0; } // Function to create flag emoji from country code function getFlagEmoji(countryCode) { if (!countryCode) return ''; const codePoints = countryCode .toLowerCase() .split('') .map(char => 127397 + char.charCodeAt()); return String.fromCodePoint(...codePoints); } // Function to create the table function createTable() { const overlay = document.querySelector('.overlay-content'); if (!overlay) return; // Find all user entries const userEntries = overlay.querySelectorAll('.block-row.block-row--separated'); if (userEntries.length === 0) return; // Create table container const tableContainer = document.createElement('div'); tableContainer.style.cssText = ` padding: 0; background: transparent; width: 100%; height: 100%; overflow: hidden; box-sizing: border-box; `; // Create search and filter container const searchFilterContainer = document.createElement('div'); searchFilterContainer.style.cssText = ` display: flex; gap: 10px; margin-bottom: 15px; align-items: center; `; // Create search input const searchInput = document.createElement('input'); searchInput.type = 'text'; searchInput.placeholder = 'Search users, countries, providers...'; searchInput.style.cssText = ` flex: 1; padding: 12px; border: 1px solid #101113; border-radius: 4px; font-size: 14px; box-sizing: border-box; background: #101113; color: #374151; `; // Create banned filter button const bannedFilterButton = document.createElement('button'); bannedFilterButton.textContent = 'Show Banned Only'; bannedFilterButton.style.cssText = ` padding: 12px 16px; border: 1px solid #dc2626; border-radius: 4px; font-size: 14px; font-weight: 500; background: #dc262620; color: #dc2626; cursor: pointer; transition: all 0.2s; white-space: nowrap; `; // Add hover effect for button bannedFilterButton.addEventListener('mouseenter', function() { this.style.backgroundColor = '#dc2626'; this.style.color = 'white'; }); bannedFilterButton.addEventListener('mouseleave', function() { if (!this.classList.contains('active')) { this.style.backgroundColor = '#dc262620'; this.style.color = '#dc2626'; } }); // Create count display const countDisplay = document.createElement('div'); countDisplay.style.cssText = ` color: #6b7280; font-size: 12px; margin-left: auto; padding: 8px 12px; background: #1a1a1a; border-radius: 4px; border: 1px solid #17191b; `; // Add button to container searchFilterContainer.appendChild(searchInput); searchFilterContainer.appendChild(bannedFilterButton); searchFilterContainer.appendChild(countDisplay); // Create table wrapper for scrolling const tableWrapper = document.createElement('div'); tableWrapper.style.cssText = ` width: 100%; overflow: auto; max-height: calc(100vh - 150px); border: 1px solid #e5e7eb; border-radius: 6px; `; // Create table const table = document.createElement('table'); table.style.cssText = ` width: 100%; min-width: 800px; border-collapse: collapse; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; font-size: 13px; margin: 0; `; // Create table header const thead = document.createElement('thead'); thead.style.cssText = `position: sticky; top: 0; z-index: 10;`; const headerRow = document.createElement('tr'); headerRow.style.cssText = `background: #101113; border-bottom: 1px solid #101113; color: #959595;`; // Username header (sortable) const usernameHeader = document.createElement('th'); usernameHeader.id = 'sort-username'; usernameHeader.style.cssText = `padding: 10px 12px; text-align: left; border-right: 1px solid #17191b; font-weight: 600; color: #959595; white-space: nowrap; cursor: pointer; user-select: none;`; usernameHeader.innerHTML = `Username ↕`; // Join Date header const joinDateHeader = document.createElement('th'); joinDateHeader.style.cssText = `padding: 10px 12px; text-align: left; border-right: 1px solid #17191b; font-weight: 600; color: #959595; white-space: nowrap;`; joinDateHeader.textContent = 'Join Date'; // Messages header const messagesHeader = document.createElement('th'); messagesHeader.style.cssText = `padding: 10px 12px; text-align: left; border-right: 1px solid #17191b; font-weight: 600; color: #959595; white-space: nowrap;`; messagesHeader.textContent = 'Messages'; // Country header const countryHeader = document.createElement('th'); countryHeader.style.cssText = `padding: 10px 12px; text-align: left; border-right: 1px solid #17191b; font-weight: 600; color: #959595; white-space: nowrap;`; countryHeader.textContent = 'Country'; // Provider header const providerHeader = document.createElement('th'); providerHeader.style.cssText = `padding: 10px 12px; text-align: left; border-right: 1px solid #17191b; font-weight: 600; color: #959595; white-space: nowrap;`; providerHeader.textContent = 'Provider'; // Type header (sortable) const typeHeader = document.createElement('th'); typeHeader.id = 'sort-type'; typeHeader.style.cssText = `padding: 10px 12px; text-align: left; border-right: 1px solid #17191b; font-weight: 600; color: #959595; white-space: nowrap; cursor: pointer; user-select: none;`; typeHeader.innerHTML = `Type ↕`; // Usage header (sortable) const usageHeader = document.createElement('th'); usageHeader.id = 'sort-usage'; usageHeader.style.cssText = `padding: 10px 12px; text-align: left; font-weight: 600; color: #959595; white-space: nowrap; cursor: pointer; user-select: none;`; usageHeader.innerHTML = `Usage ↕`; // Append all headers to row headerRow.appendChild(usernameHeader); headerRow.appendChild(joinDateHeader); headerRow.appendChild(messagesHeader); headerRow.appendChild(countryHeader); headerRow.appendChild(providerHeader); headerRow.appendChild(typeHeader); headerRow.appendChild(usageHeader); thead.appendChild(headerRow); // Create table body const tbody = document.createElement('tbody'); // Process each user entry userEntries.forEach((entry, index) => { const row = document.createElement('tr'); row.style.cssText = ` border-bottom: 1px solid #17191b; transition: background-color 0.2s; `; row.style.backgroundColor = index % 2 === 0 ? '#131313' : '#131313'; // Username const usernameLink = entry.querySelector('h3.contentRow-header a.username'); const username = usernameLink ? usernameLink.textContent.trim() : 'N/A'; const profileUrl = usernameLink ? usernameLink.href : '#'; // Check if user is banned const usernameSpan = entry.querySelector('h3.contentRow-header a.username span'); const isBanned = usernameSpan && usernameSpan.classList.contains('username--banned'); // Join date const joinDateElement = entry.querySelector('time.u-dt'); const joinDate = joinDateElement ? joinDateElement.textContent.trim() : 'N/A'; // Messages const dtElements = entry.querySelectorAll('dt'); let messagesElement = null; for (const dt of dtElements) { if (dt.textContent.includes('Messages')) { messagesElement = dt; break; } } const messages = messagesElement ? (messagesElement.nextElementSibling ? messagesElement.nextElementSibling.textContent.trim() : '0') : '0'; // Country flag and name const flagElement = entry.querySelector('.tck-provider-country-flag'); const countryCode = flagElement ? getCountryCode(flagElement) : ''; const countryName = flagElement ? getCountryName(flagElement) : ''; const flagEmoji = getFlagEmoji(countryCode); // Provider info const providerElement = entry.querySelector('.tck-provider-txt'); const providerInfo = providerElement ? getProviderInfo(providerElement) : { name: 'N/A', asn: '' }; // Type info const typeElement = entry.querySelector('.tck-provider-type'); const typeInfo = typeElement ? getTypeInfo(typeElement) : 'N/A'; // Usage count const liElements = entry.querySelectorAll('li'); let usageElement = null; for (const li of liElements) { if (li.textContent.includes('time')) { usageElement = li; break; } } const usageText = usageElement ? usageElement.textContent.trim() : '0 time'; const usageCount = getUsageCount(usageText); // Build row HTML row.innerHTML = `