您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Really ignores ignored users
// ==UserScript== // @name Cook'd and Bomb'd Really Ignore Users // @description Really ignores ignored users // @namespace https://github.com/insin/greasemonkey/ // @version 3 // @match https://www.cookdandbombd.co.uk/forums/index.php?board* // @match https://www.cookdandbombd.co.uk/forums/index.php?topic* // @match https://www.cookdandbombd.co.uk/forums/index.php?action=post* // @match https://www.cookdandbombd.co.uk/forums/index.php?action=profile;area=lists;sa=ignore* // @match https://www.cookdandbombd.co.uk/forums/index.php?action=unread* // @grant GM.registerMenuCommand // ==/UserScript== const IGNORED_USERS_STORAGE = 'cab_ignoredUsers' let config = { addIgnoreUserControlToPosts: true, hidePostsQuotingIgnoredUsers: true, hideTopicsCreatedByIgnoredUsers: true, showIgnoredPosts: false, } let posts = [] function addStyle(css) { let $style = document.createElement('style') $style.appendChild(document.createTextNode(css)) document.head.appendChild($style) } function addIgnoredPostsStyle() { addStyle(` .cab_ignoredPost { display: none; } .cab_ignoredPost.cab_show { display: block; background-color: #ddd !important; } `) } function getIgnoredUsers() { return JSON.parse(localStorage[IGNORED_USERS_STORAGE] || '[]') } function storeIgnoredUsers(ignoredUsers) { localStorage[IGNORED_USERS_STORAGE] = JSON.stringify(ignoredUsers) } function toggleShowIgnoredPosts(showIgnoredPosts) { config.showIgnoredPosts = showIgnoredPosts posts.forEach(post => post.updateClassNames()) } /** * Topics being hidden breaks the CSS nth-of-type striping. */ function reStripePosts() { let odd = true posts.forEach(post => { if (!post.isIgnored()) { post.$el.classList.toggle('odd', odd) post.$el.classList.toggle('even', !odd) odd = !odd } else { post.$el.classList.remove('odd') post.$el.classList.remove('even') } }) } function TopicPage() { addIgnoredPostsStyle() let isLoggedIn = document.querySelector('#profile_menu_top') != null let ignoredUsers let ignoredUserIds let ignoredUserNames function setIgnoredUsers(ignoreList) { ignoredUsers = ignoreList ignoredUserIds = ignoredUsers.map(user => user.id) ignoredUserNames = ignoredUsers.map(user => user.name) } function configureIgnoreControl({$a, $span, userId, userName}) { let isUserIgnored = ignoredUserIds.includes(userId) $a.href = `https://www.cookdandbombd.co.uk/forums/index.php?action=profile;area=lists;sa=ignore&${isUserIgnored ? `unignore=${userId}` : `ignore=${userName}`}` $a.title = `${isUserIgnored ? 'Remove from' : 'Add to'} ignore list` $span.classList.toggle('delete', isUserIgnored) $span.classList.toggle('ignore', !isUserIgnored) } function Post($wrapper) { let $userLink = $wrapper.querySelector('div.poster h4 a') let userId = $userLink.href.match(/;u=(\d+)/)[1] let userName = $userLink.textContent let quotedUserNames = Array.from($wrapper.querySelectorAll('.post blockquote cite a')).map( $a => $a.textContent.match(/Quote from: (.+) on /)?.[1] || $a.textContent.match(/Quote from: (.+)/)?.[1] ).filter(Boolean) let api = { $el: $wrapper, isIgnored() { let isUserIgnored = ignoredUserIds.includes(userId) let quotesIgnoredUser = config.hidePostsQuotingIgnoredUsers && quotedUserNames.some(userName => ignoredUserNames.includes(userName)) return isUserIgnored || quotesIgnoredUser }, updateClassNames() { let isPostIgnored = api.isIgnored() $wrapper.classList.toggle('cab_ignoredPost', isPostIgnored) $wrapper.classList.toggle('cab_show', config.showIgnoredPosts && isPostIgnored) } } // Add an ignore/unignore link to user profiles in posts if (config.addIgnoreUserControlToPosts) { let $a = document.createElement('a') let $span = document.createElement('span') $span.className = 'main_icons centericon' $a.appendChild($span) let $li = document.createElement('li') $li.appendChild($a) configureIgnoreControl({$a, $span, userId, userName}) let $profileIcons = $wrapper.querySelector('div.poster ol.profile_icons') // Logged-out users don't get a profile list item, so we'll add our own if (!$profileIcons) { let $insertProfileAfter = $wrapper.querySelector('div.poster .im_icons') || $wrapper.querySelector('div.poster .blurb') || $wrapper.querySelector('div.poster .icons') let $profile = document.createElement('li') $profile.className = 'profile' $profileIcons = document.createElement('ol') $profileIcons.className = 'profile' $profile.appendChild($profileIcons) $insertProfileAfter.insertAdjacentElement('afterend', $profile) } $profileIcons.appendChild($li) // For logged-out users, manage the ignore list independently if (!isLoggedIn) { $a.addEventListener('click', (e) => { e.preventDefault() // Get a fresh copy in case it's been changed in another tab let ignoredUsers = getIgnoredUsers() let index = ignoredUsers.findIndex(user => user.id === userId) if (index != -1) { ignoredUsers.splice(index, 1) } else { ignoredUsers.push({id: userId, name: userName}) } setIgnoredUsers(ignoredUsers) storeIgnoredUsers(ignoredUsers) configureIgnoreControl({$a, $span, userId, userName}) posts.forEach(post => post.updateClassNames()) reStripePosts() }) } } api.updateClassNames() return api } let postElements = Array.from(document.querySelectorAll('#forumposts > form > div.windowbg')) let oddBg = postElements[0] ? getComputedStyle(postElements[0]).backgroundColor : null let evenBg = postElements[1] ? getComputedStyle(postElements[1]).backgroundColor : null addStyle(` .cab_ignoredPost { display: none; } .cab_ignoredPost.cab_show { display: block; background-color: #ddd !important; } ${oddBg ? `#forumposts .windowbg.odd { background-color: ${oddBg}; }` : ''} ${evenBg ? `#forumposts .windowbg.even { background-color: ${evenBg}; }` : ''} `) setIgnoredUsers(getIgnoredUsers()) posts = postElements.map(Post) reStripePosts() document.body.classList.add('cab_reallyIgnoreUsers') } function PostReplyPage() { let ignoredUserNames = getIgnoredUsers().map(user => user.name) function Post($wrapper) { let $userHeader = $wrapper.querySelector('h5') let userName = $userHeader?.textContent.match(/Posted by (.+)/)?.[1] let quotedUserNames = Array.from($wrapper.querySelectorAll('blockquote cite a')).map( $a => $a.textContent.match(/Quote from: (.+) on /)?.[1] || $a.textContent.match(/Quote from: (.+)/)?.[1] ).filter(Boolean) let api = { $el: $wrapper, isIgnored() { let isUserIgnored = ignoredUserNames.includes(userName) let quotesIgnoredUser = config.hidePostsQuotingIgnoredUsers && quotedUserNames.some(userName => ignoredUserNames.includes(userName)) return isUserIgnored || quotesIgnoredUser }, updateClassNames() { let isPostIgnored = api.isIgnored() $wrapper.classList.toggle('cab_ignoredPost', isPostIgnored) $wrapper.classList.toggle('cab_show', config.showIgnoredPosts && isPostIgnored) } } api.updateClassNames() return api } let postElements = Array.from(document.querySelectorAll('#recent div.windowbg')) let oddBg = postElements[0] ? getComputedStyle(postElements[0]).backgroundColor : null let evenBg = postElements[1] ? getComputedStyle(postElements[1]).backgroundColor : null addStyle(` .cab_ignoredPost { display: none; } .cab_ignoredPost.cab_show { display: block; background-color: #ddd !important; } ${oddBg ? `#recent .windowbg.odd { background-color: ${oddBg}; }` : ''} ${evenBg ? `#recent .windowbg.even { background-color: ${evenBg}; }` : ''} `) posts = postElements.map(Post) reStripePosts() document.body.classList.add('cab_reallyIgnoreUsers') } function IgnoreListPage() { let params = new URLSearchParams(location.search) // Automatically ignore a user if ignore=name is provided in the URL if (params.has('ignore')) { let $newIgnoreInput = document.querySelector('#new_ignore') $newIgnoreInput.value = params.get('ignore') $newIgnoreInput.form.submit() return } // Automatically unignore a user if unignore=id is provided in the URL if (params.has('unignore')) { let $removeLink = Array.from(document.querySelectorAll('.table_grid tr td:last-child a')).find( $a => $a.href.includes(`remove=${params.get('unignore')}`) ) if ($removeLink) { $removeLink.click() return } } // Otherwise sync with the ignore list let ignoredUsers = Array.from(document.querySelectorAll('.table_grid tr td:first-child a')).map($a => ({ id: $a.href.match(/;u=(\d+)/)[1], name: $a.textContent, })) storeIgnoredUsers(ignoredUsers) } function ForumPage() { addStyle(` #topic_container .windowbg.cab_ignoredUser { display: none; } `) let ignoredUserIds = getIgnoredUsers().map(user => user.id) for (let $topicRow of document.querySelectorAll('#topic_container > div')) { let $userLink = $topicRow.querySelector('.info .floatleft a') let userId = $userLink?.href.match(/;u=(\d+)/)?.[1] if (ignoredUserIds.includes(userId)) { $topicRow.classList.add('cab_ignoredUser') } } } if (location.search.includes('?action=profile;area=lists;sa=ignore')) { IgnoreListPage() } else if (location.search.includes('?action=unread') || location.search.includes('?board')) { if (config.hideTopicsCreatedByIgnoredUsers) { ForumPage() } } else if (!document.body.classList.contains('cab_reallyIgnoreUsers')) { let page = location.search.includes('?action=post') ? PostReplyPage : TopicPage if (typeof GM != 'undefined') { page() GM.registerMenuCommand('Toggle ignored post display', () => { toggleShowIgnoredPosts(!config.showIgnoredPosts) }) } else { chrome.storage.local.get((storedConfig) => { Object.assign(config, storedConfig) page() }) chrome.storage.onChanged.addListener((changes) => { if ('showIgnoredPosts' in changes) { toggleShowIgnoredPosts(changes['showIgnoredPosts'].newValue) } }) } }