Created
September 4, 2026 15:13
-
-
Save i30817/04506a8bab2fd32ac0a071e14d05173e to your computer and use it in GitHub Desktop.
block users in spacebattles without limiand logged outt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // ==UserScript== | |
| // @name Spacebattles Filter (Main Page Native Hook) | |
| // @namespace http://tampermonkey.net | |
| // @version 6.9.2 | |
| // @description Hides threads by specific users. Adds a script block/unblock button instantly inside XenForo's native hover member card tooltips. Adds New Threadmarks filtering. | |
| // @author AI Assistant | |
| // @match https://forums.spacebattles.com/* | |
| // @grant GM_setValue | |
| // @grant GM_getValue | |
| // @run-at document-start | |
| // ==/UserScript== | |
| (function() { | |
| 'use strict'; | |
| let blockedUsers = GM_getValue("sb_loggedout_blocks", []); | |
| function scrubContent() { | |
| // --- ORIGINAL 6.9 BLOCKING MECHANICS --- | |
| const threads = document.querySelectorAll('div.structItem[data-author]'); | |
| threads.forEach(thread => { | |
| if (!thread) return; | |
| const author = thread.getAttribute('data-author'); | |
| if (author && blockedUsers.includes(author.toLowerCase().trim())) { | |
| thread.remove(); | |
| } | |
| }); | |
| const feeds = document.querySelectorAll('.js-newsFeedTarget [data-author]'); | |
| feeds.forEach(item => { | |
| if (!item) return; | |
| const author = item.getAttribute('data-author'); | |
| if (author && blockedUsers.includes(author.toLowerCase().trim())) { | |
| item.remove(); | |
| } | |
| }); | |
| const activityLinks = document.querySelectorAll('.js-newsFeedTarget a.username[data-user-id], [data-template="whats_new"] a.username[data-user-id]'); | |
| activityLinks.forEach(link => { | |
| if (!link) return; | |
| const author = link.textContent.toLowerCase().trim(); | |
| if (blockedUsers.includes(author)) { | |
| const targetRow = link.closest('.contentRow, li, .block-row'); | |
| if (targetRow) { | |
| targetRow.remove(); | |
| } | |
| } | |
| }); | |
| // --- NEW THREADMARKS SEPARATED FIX --- | |
| // New Threadmarks views organize lists via table row syntax ("tr") rather than standard blocks ("div") | |
| const threadmarkRows = document.querySelectorAll('tr.structItem[data-author]'); | |
| threadmarkRows.forEach(row => { | |
| if (!row) return; | |
| const author = row.getAttribute('data-author'); | |
| if (author && blockedUsers.includes(author.toLowerCase().trim())) { | |
| row.remove(); | |
| } | |
| }); | |
| // Deep match nested threadmark item container lists | |
| const threadmarkContainers = document.querySelectorAll('.structItem--threadmark'); | |
| threadmarkContainers.forEach(container => { | |
| const authorLink = container.querySelector('a.username[data-user-id]'); | |
| if (authorLink) { | |
| const author = authorLink.textContent.toLowerCase().trim(); | |
| if (blockedUsers.includes(author)) { | |
| container.remove(); | |
| } | |
| } | |
| }); | |
| } | |
| function injectTooltipUI() { | |
| const actionContainers = document.querySelectorAll('.memberTooltip-actions'); | |
| actionContainers.forEach(actionContainer => { | |
| if (actionContainer.querySelector('.sb-tooltip-btn')) return; | |
| const tooltip = actionContainer.closest('.tooltip--member'); | |
| if (!tooltip) return; | |
| const nameNode = tooltip.querySelector('.memberTooltip-name'); | |
| if (!nameNode) return; | |
| const username = nameNode.textContent.replace(/\[.*?\]/g, '').split('\n').join('').trim(); | |
| if (!username) return; | |
| const normalizedName = username.toLowerCase(); | |
| const isBlocked = blockedUsers.includes(normalizedName); | |
| const btn = document.createElement('button'); | |
| btn.type = 'button'; | |
| btn.className = 'button button--link sb-tooltip-btn'; | |
| btn.style.padding = '6px 10px'; | |
| btn.style.fontSize = '12px'; | |
| btn.style.fontWeight = 'bold'; | |
| btn.style.cursor = 'pointer'; | |
| btn.style.marginLeft = '5px'; | |
| btn.style.display = 'inline-block'; | |
| btn.style.verticalAlign = 'middle'; | |
| if (isBlocked) { | |
| btn.textContent = `Unblock (Script)`; | |
| btn.style.backgroundColor = '#cc2424'; | |
| btn.style.color = '#ffffff'; | |
| btn.style.borderColor = '#b31c1c'; | |
| } else { | |
| btn.textContent = `Block (Script)`; | |
| btn.style.backgroundColor = '#0066cc'; | |
| btn.style.color = '#ffffff'; | |
| btn.style.borderColor = '#0052a3'; | |
| } | |
| btn.addEventListener('click', (e) => { | |
| e.preventDefault(); | |
| e.stopPropagation(); | |
| if (blockedUsers.includes(normalizedName)) { | |
| blockedUsers = blockedUsers.filter(name => name !== normalizedName); | |
| } else { | |
| blockedUsers.push(normalizedName); | |
| } | |
| GM_setValue("sb_loggedout_blocks", blockedUsers); | |
| window.location.reload(); | |
| }); | |
| actionContainer.appendChild(btn); | |
| }); | |
| } | |
| function injectMobileUI() { | |
| if (!window.location.pathname.includes('/members/')) return; | |
| const targetHeader = document.querySelector('.memberHeader > .memberHeader-content, .memberHeader-content'); | |
| if (!targetHeader || targetHeader.querySelector('.sb-mobile-btn')) return; | |
| const nameNode = targetHeader.querySelector('.memberHeader-name, h1, h2'); | |
| if (!nameNode) return; | |
| const username = nameNode.textContent.replace(/\[.*?\]/g, '').split('\n').join('').trim(); | |
| if (!username) return; | |
| const normalizedName = username.toLowerCase(); | |
| const isBlocked = blockedUsers.includes(normalizedName); | |
| const btnWrapper = document.createElement('div'); | |
| btnWrapper.className = 'sb-mobile-btn'; | |
| btnWrapper.style.margin = '15px 0 5px 0'; | |
| btnWrapper.style.width = '100%'; | |
| btnWrapper.style.clear = 'both'; | |
| btnWrapper.style.display = 'block'; | |
| const btn = document.createElement('button'); | |
| btn.type = 'button'; | |
| btn.style.padding = '12px 16px'; | |
| btn.style.fontSize = '14px'; | |
| btn.style.fontWeight = 'bold'; | |
| btn.style.border = '1px solid rgba(255,255,255,0.15)'; | |
| btn.style.borderRadius = '4px'; | |
| btn.style.cursor = 'pointer'; | |
| btn.style.width = '100%'; | |
| btn.style.textAlign = 'center'; | |
| btn.style.boxShadow = '0 2px 5px rgba(0,0,0,0.4)'; | |
| // Extracted variables securely without forcing string modifications on line layout bounds | |
| if (isBlocked) { | |
| btn.textContent = "Unblock " + username + " (Script)"; | |
| btn.style.backgroundColor = '#cc2424'; | |
| btn.style.color = '#ffffff'; | |
| } else { | |
| btn.textContent = "Block " + username + " (Script)"; | |
| btn.style.backgroundColor = '#0066cc'; | |
| btn.style.color = '#ffffff'; | |
| } | |
| btn.addEventListener('click', (e) => { | |
| e.preventDefault(); | |
| e.stopPropagation(); | |
| if (blockedUsers.includes(normalizedName)) { | |
| blockedUsers = blockedUsers.filter(name => name !== normalizedName); | |
| alert('"' + username + '" has been unblocked.'); | |
| } else { | |
| blockedUsers.push(normalizedName); | |
| alert('"' + username + '" has been blocked.'); | |
| } | |
| GM_setValue("sb_loggedout_blocks", blockedUsers); | |
| window.location.reload(); | |
| }); | |
| btnWrapper.appendChild(btn); | |
| targetHeader.appendChild(btnWrapper); | |
| } | |
| function handleDashboardVisibility() { | |
| const isMainPage = document.body && document.body.getAttribute('data-template') === 'forum_list'; | |
| const existingToggle = document.getElementById('sb-filter-dashboard-toggle'); | |
| const existingPanel = document.getElementById('sb-filter-dashboard-panel'); | |
| if (!isMainPage) { | |
| if (existingToggle) existingToggle.style.display = 'none'; | |
| if (existingPanel) existingPanel.style.display = 'none'; | |
| return; | |
| } | |
| if (existingToggle) { | |
| existingToggle.style.display = 'flex'; | |
| return; | |
| } | |
| const toggleBtn = document.createElement('button'); | |
| toggleBtn.id = 'sb-filter-dashboard-toggle'; | |
| toggleBtn.innerHTML = '⚙️'; | |
| toggleBtn.style.position = 'fixed'; | |
| toggleBtn.style.bottom = '25px'; | |
| toggleBtn.style.right = '25px'; | |
| toggleBtn.style.zIndex = '10000'; | |
| toggleBtn.style.backgroundColor = '#1f487e'; | |
| toggleBtn.style.color = '#ffffff'; | |
| toggleBtn.style.border = '2px solid #ffffff'; | |
| toggleBtn.style.borderRadius = '50%'; | |
| toggleBtn.style.width = '50px'; | |
| toggleBtn.style.height = '50px'; | |
| toggleBtn.style.fontSize = '24px'; | |
| toggleBtn.style.cursor = 'pointer'; | |
| toggleBtn.style.display = 'flex'; | |
| toggleBtn.style.alignItems = 'center'; | |
| toggleBtn.style.justifyContent = 'center'; | |
| toggleBtn.style.boxShadow = '0 4px 8px rgba(0,0,0,0.4)'; | |
| const panel = document.createElement('div'); | |
| panel.id = 'sb-filter-dashboard-panel'; | |
| panel.style.position = 'fixed'; | |
| panel.style.bottom = '85px'; | |
| panel.style.right = '25px'; | |
| panel.style.width = '280px'; | |
| panel.style.maxHeight = '350px'; | |
| panel.style.backgroundColor = '#1d2025'; | |
| panel.style.color = '#e1e2e6'; | |
| panel.style.border = '1px solid #3e4550'; | |
| panel.style.borderRadius = '8px'; | |
| panel.style.boxShadow = '0px 4px 15px rgba(0,0,0,0.5)'; | |
| panel.style.zIndex = '10000'; | |
| panel.style.display = 'none'; | |
| panel.style.flexDirection = 'column'; | |
| panel.style.overflow = 'hidden'; | |
| const header = document.createElement('div'); | |
| header.style.padding = '12px'; | |
| header.style.backgroundColor = '#141619'; | |
| header.style.fontWeight = 'bold'; | |
| header.style.borderBottom = '1px solid #3e4550'; | |
| header.style.display = 'flex'; | |
| header.style.justifyContent = 'space-between'; | |
| header.style.alignItems = 'center'; | |
| header.innerHTML = 'Blocked Users'; | |
| const closeBtn = document.createElement('span'); | |
| closeBtn.innerHTML = '×'; | |
| closeBtn.style.cursor = 'pointer'; | |
| closeBtn.style.fontSize = '20px'; | |
| closeBtn.addEventListener('click', () => { | |
| panel.style.display = 'none'; | |
| }); | |
| header.appendChild(closeBtn); | |
| panel.appendChild(header); | |
| const listBody = document.createElement('div'); | |
| listBody.style.padding = '10px'; | |
| listBody.style.overflowY = 'auto'; | |
| listBody.style.flexGrow = '1'; | |
| panel.appendChild(listBody); | |
| toggleBtn.addEventListener('click', () => { | |
| if (panel.style.display === 'none') { | |
| renderListItems(listBody); | |
| panel.style.display = 'flex'; | |
| } | |
| else { | |
| panel.style.display = 'none'; | |
| } | |
| }); | |
| document.body.appendChild(toggleBtn); | |
| document.body.appendChild(panel); | |
| } | |
| function renderListItems(container) { | |
| container.innerHTML = ''; | |
| if (blockedUsers.length === 0) { | |
| container.innerHTML = 'No users blocked yet.'; | |
| return; | |
| } | |
| blockedUsers.forEach(user => { | |
| const row = document.createElement('div'); | |
| row.style.display = 'flex'; | |
| row.style.justifyContent = 'space-between'; | |
| row.style.alignItems = 'center'; | |
| row.style.padding = '8px 0'; | |
| row.style.borderBottom = '1px solid #282c34'; | |
| const nameSpan = document.createElement('span'); | |
| nameSpan.textContent = user; | |
| nameSpan.style.fontSize = '14px'; | |
| const removeBtn = document.createElement('button'); | |
| removeBtn.type = 'button'; | |
| removeBtn.textContent = 'Remove'; | |
| removeBtn.style.backgroundColor = '#a71d5d'; | |
| removeBtn.style.color = '#ffffff'; | |
| removeBtn.style.border = 'none'; | |
| removeBtn.style.borderRadius = '3px'; | |
| removeBtn.style.padding = '4px 8px'; | |
| removeBtn.style.cursor = 'pointer'; | |
| removeBtn.addEventListener('click', () => { | |
| blockedUsers = blockedUsers.filter(name => name !== user); | |
| GM_setValue("sb_loggedout_blocks", blockedUsers); | |
| row.remove(); | |
| if (blockedUsers.length === 0) { | |
| container.innerHTML = 'No users blocked yet.'; | |
| } | |
| }); | |
| row.appendChild(nameSpan); | |
| row.appendChild(removeBtn); | |
| container.appendChild(row); | |
| }); | |
| } | |
| function masterLoop() { | |
| scrubContent(); | |
| injectTooltipUI(); | |
| injectMobileUI(); | |
| handleDashboardVisibility(); | |
| } | |
| masterLoop(); | |
| const globalObserver = new MutationObserver(masterLoop); | |
| globalObserver.observe(document.documentElement, { childList: true, subtree: true }); | |
| })(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment