Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // ==UserScript==
- // @name Blockland Forum User Blocker
- // @namespace http://tampermonkey.net/
- // @version 1.1
- // @description Block and censor posts, topics, and board activity from specific users on the Blockland forums
- // @match https://forum.blockland.us/*
- // @grant GM_getValue
- // @grant GM_setValue
- // @grant GM_registerMenuCommand
- // ==/UserScript==
- (function () {
- 'use strict';
- // --- Blocklist Management ---
- function getBlocklist() {
- const raw = GM_getValue('blocklist', '[]');
- try {
- return JSON.parse(raw);
- } catch {
- return [];
- }
- }
- function saveBlocklist(list) {
- GM_setValue('blocklist', JSON.stringify(list));
- }
- function isBlocked(username) {
- return getBlocklist().some((n) => n.toLowerCase() === username.toLowerCase());
- }
- // --- Settings ---
- function getHideMode() {
- return GM_getValue('hideMode', 'censor'); // 'censor' or 'hide'
- }
- function setHideMode(mode) {
- GM_setValue('hideMode', mode);
- }
- // Generic avatar as a data URI (simple silhouette)
- const GENERIC_AVATAR = 'data:image/svg+xml,' + encodeURIComponent(
- '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 80 80" fill="#555" background="#333">' +
- '<rect width="80" height="80" fill="#333"/>' +
- '<circle cx="40" cy="28" r="14" fill="#555"/>' +
- '<ellipse cx="40" cy="70" rx="24" ry="18" fill="#555"/>' +
- '</svg>'
- );
- function addToBlocklist(username) {
- const current = getBlocklist();
- if (!current.some((n) => n.toLowerCase() === username.toLowerCase())) {
- current.push(username);
- saveBlocklist(current);
- runAll();
- }
- }
- // --- UI: Blocklist Editor Panel ---
- function createBlocklistPanel() {
- if (document.getElementById('blf-blocklist-panel')) {
- document.getElementById('blf-blocklist-panel').remove();
- return;
- }
- const overlay = document.createElement('div');
- overlay.id = 'blf-blocklist-panel';
- overlay.style.cssText = `
- position: fixed; top: 0; left: 0; width: 100%; height: 100%;
- background: rgba(0,0,0,0.6); z-index: 99999;
- display: flex; align-items: center; justify-content: center;
- `;
- const panel = document.createElement('div');
- panel.style.cssText = `
- background: #e9eef2; color: #444; border: 1px solid #a9b7c0;
- border-radius: 4px; padding: 20px; width: 400px; max-height: 80vh;
- box-shadow: 0 4px 16px rgba(0,0,0,0.3);
- font: 12px Verdana, Arial, Helvetica, sans-serif;
- display: flex; flex-direction: column;
- `;
- const title = document.createElement('h2');
- title.textContent = 'Blocked Users';
- title.style.cssText = 'margin: 0 0 12px 0; font-size: 16px; color: #346; font-family: Verdana, Arial, Helvetica, sans-serif;';
- panel.appendChild(title);
- const listContainer = document.createElement('div');
- listContainer.style.cssText = 'flex: 1; overflow-y: auto; margin-bottom: 12px; max-height: 300px;';
- function renderList() {
- listContainer.innerHTML = '';
- const current = getBlocklist();
- if (current.length === 0) {
- const empty = document.createElement('div');
- empty.textContent = 'No blocked users yet. Add one below.';
- empty.style.cssText = 'color: #888; font-size: 11px; padding: 10px 0;';
- listContainer.appendChild(empty);
- } else {
- current.forEach((name) => {
- const row = document.createElement('div');
- row.style.cssText = `
- display: flex; align-items: center; justify-content: space-between;
- padding: 5px 8px; margin-bottom: 3px; background: #d4dae0; border-radius: 2px;
- `;
- const label = document.createElement('span');
- label.textContent = name;
- label.style.cssText = 'font-size: 12px; color: #444;';
- const removeBtn = document.createElement('button');
- removeBtn.textContent = 'Unblock';
- removeBtn.style.cssText = `
- background: none; color: #346; border: none;
- padding: 2px 0; cursor: pointer; font: 11px Verdana, Arial, Helvetica, sans-serif;
- text-decoration: underline;
- `;
- removeBtn.addEventListener('click', () => {
- const updated = getBlocklist().filter((n) => n !== name);
- saveBlocklist(updated);
- renderList();
- runAll();
- });
- row.appendChild(label);
- row.appendChild(removeBtn);
- listContainer.appendChild(row);
- });
- }
- }
- renderList();
- panel.appendChild(listContainer);
- // Add user input
- const addRow = document.createElement('div');
- addRow.style.cssText = 'display: flex; gap: 8px;';
- const input = document.createElement('input');
- input.type = 'text';
- input.placeholder = 'Enter username to block...';
- input.style.cssText = `
- flex: 1; padding: 4px 8px; border-radius: 2px; border: 1px solid #a9b7c0;
- background: #fff; color: #444; font: 12px Verdana, Arial, Helvetica, sans-serif;
- `;
- const addBtn = document.createElement('button');
- addBtn.textContent = 'Block';
- addBtn.style.cssText = `
- background: #d4dae0; color: #346; border: 1px solid #a9b7c0; border-radius: 2px;
- padding: 4px 12px; cursor: pointer; font: 12px Verdana, Arial, Helvetica, sans-serif;
- `;
- function addUser() {
- const name = input.value.trim();
- if (!name) return;
- addToBlocklist(name);
- renderList();
- input.value = '';
- }
- addBtn.addEventListener('click', addUser);
- input.addEventListener('keydown', (e) => {
- if (e.key === 'Enter') addUser();
- });
- addRow.appendChild(input);
- addRow.appendChild(addBtn);
- panel.appendChild(addRow);
- // Hide mode setting
- const settingsRow = document.createElement('div');
- settingsRow.style.cssText = 'margin-top: 14px; padding-top: 12px; border-top: 1px solid #a9b7c0;';
- const settingsLabel = document.createElement('div');
- settingsLabel.textContent = 'Block Mode';
- settingsLabel.style.cssText = 'font-size: 12px; font-weight: bold; margin-bottom: 6px; color: #346;';
- settingsRow.appendChild(settingsLabel);
- const currentMode = getHideMode();
- const censorRadio = document.createElement('input');
- censorRadio.type = 'radio';
- censorRadio.name = 'blf-hide-mode';
- censorRadio.value = 'censor';
- censorRadio.id = 'blf-mode-censor';
- censorRadio.checked = currentMode === 'censor';
- const censorLabel = document.createElement('label');
- censorLabel.htmlFor = 'blf-mode-censor';
- censorLabel.textContent = ' Censor & anonymize (show placeholder)';
- censorLabel.style.cssText = 'font-size: 11px; cursor: pointer; color: #444;';
- const hideRadio = document.createElement('input');
- hideRadio.type = 'radio';
- hideRadio.name = 'blf-hide-mode';
- hideRadio.value = 'hide';
- hideRadio.id = 'blf-mode-hide';
- hideRadio.checked = currentMode === 'hide';
- const hideLabel = document.createElement('label');
- hideLabel.htmlFor = 'blf-mode-hide';
- hideLabel.textContent = ' Completely hide (remove from page)';
- hideLabel.style.cssText = 'font-size: 11px; cursor: pointer; color: #444;';
- const row1 = document.createElement('div');
- row1.style.marginBottom = '4px';
- row1.appendChild(censorRadio);
- row1.appendChild(censorLabel);
- const row2 = document.createElement('div');
- row2.appendChild(hideRadio);
- row2.appendChild(hideLabel);
- settingsRow.appendChild(row1);
- settingsRow.appendChild(row2);
- function onModeChange() {
- setHideMode(this.value);
- runAll();
- }
- censorRadio.addEventListener('change', onModeChange);
- hideRadio.addEventListener('change', onModeChange);
- panel.appendChild(settingsRow);
- // Close button
- const closeBtn = document.createElement('button');
- closeBtn.textContent = 'Close';
- closeBtn.style.cssText = `
- margin-top: 12px; background: #d4dae0; color: #346; border: 1px solid #a9b7c0;
- border-radius: 2px; padding: 6px; cursor: pointer;
- font: 12px Verdana, Arial, Helvetica, sans-serif;
- `;
- closeBtn.addEventListener('click', () => overlay.remove());
- panel.appendChild(closeBtn);
- overlay.appendChild(panel);
- overlay.addEventListener('click', (e) => {
- if (e.target === overlay) overlay.remove();
- });
- document.body.appendChild(overlay);
- }
- // --- Inject CSS ---
- const style = document.createElement('style');
- style.textContent = `
- /* === Censored posts (topic view) === */
- .blf-censored .poster h4 a,
- .blf-censored .poster h4 {
- color: #666 !important;
- font-style: italic;
- }
- /* avatar is replaced via JS with a generic silhouette */
- /* === Completely hidden mode === */
- div.windowbg.blf-hidden,
- div.windowbg2.blf-hidden {
- display: none !important;
- }
- tr.blf-topic-hidden {
- display: none !important;
- }
- .blf-censored .post .inner {
- position: relative;
- color: transparent !important;
- user-select: none;
- }
- .blf-censored .post .inner * {
- color: transparent !important;
- visibility: hidden;
- }
- .blf-censored .post .inner::after {
- content: 'This post has been hidden because the user is on your blocklist.';
- position: absolute;
- top: 0; left: 0; right: 0; bottom: 0;
- display: flex; align-items: center; justify-content: center;
- color: #888;
- font-style: italic;
- font-size: 13px;
- background: repeating-linear-gradient(
- 45deg,
- transparent,
- transparent 10px,
- rgba(100,100,100,0.08) 10px,
- rgba(100,100,100,0.08) 20px
- );
- visibility: visible;
- }
- .blf-censored .post .inner img,
- .blf-censored .post .inner iframe,
- .blf-censored .post .inner video,
- .blf-censored .post .inner embed {
- display: none !important;
- }
- .blf-censored .postarea .keyinfo {
- visibility: visible;
- }
- /* === Censored topic rows (board view) === */
- tr.blf-topic-censored td {
- opacity: 0.4;
- }
- tr.blf-topic-censored td.subject span a {
- color: #666 !important;
- }
- tr.blf-topic-censored td.subject p {
- font-style: italic;
- color: #666 !important;
- }
- tr.blf-topic-censored td.subject p a {
- color: #666 !important;
- }
- /* === Censored "last post by" on board index and topic listing === */
- .blf-lastpost-censored {
- font-style: italic;
- opacity: 0.4;
- }
- .blf-lastpost-censored a {
- color: #666 !important;
- }
- /* === Censored quotes === */
- .quoteheader.blf-quote-censored div a {
- color: #666 !important;
- font-style: italic;
- }
- blockquote.blf-quote-censored {
- position: relative;
- color: transparent !important;
- user-select: none;
- }
- blockquote.blf-quote-censored * {
- color: transparent !important;
- visibility: hidden;
- }
- blockquote.blf-quote-censored img,
- blockquote.blf-quote-censored iframe,
- blockquote.blf-quote-censored video,
- blockquote.blf-quote-censored embed {
- display: none !important;
- }
- blockquote.blf-quote-censored::after {
- content: 'Quoted content from a blocked user has been hidden.';
- position: absolute;
- top: 0; left: 0; right: 0; bottom: 0;
- display: flex; align-items: center; justify-content: center;
- color: #888;
- font: italic 11px Verdana, Arial, Helvetica, sans-serif;
- visibility: visible;
- }
- /* Show/hide toggle button — styled as a native forum smalltext link */
- .blf-show-btn {
- background: none; border: none;
- color: #346; cursor: pointer;
- font: 11px Verdana, Arial, Helvetica, sans-serif;
- margin-left: 6px; padding: 0;
- text-decoration: underline;
- }
- .blf-show-btn:hover { color: #c06002; }
- /* Block user link in poster sidebar — matches forum smalltext links */
- .blf-block-link {
- cursor: pointer;
- color: #346;
- font: 10px Verdana, Arial, Helvetica, sans-serif;
- display: block; margin-top: 4px;
- margin-left: 16px;
- }
- .blf-block-link:hover { color: #c06002; text-decoration: underline; }
- /* Inline topic row show button — same smalltext link style */
- .blf-topic-show-btn {
- background: none; border: none;
- color: #346; cursor: pointer;
- font: 10px Verdana, Arial, Helvetica, sans-serif;
- margin-left: 6px; padding: 0;
- text-decoration: underline;
- vertical-align: middle;
- }
- .blf-topic-show-btn:hover { color: #c06002; }
- `;
- document.head.appendChild(style);
- // =============================================
- // 1) TOPIC VIEW: Filter/censor individual posts
- // =============================================
- function filterPosts() {
- const posts = document.querySelectorAll('div.windowbg, div.windowbg2');
- if (posts.length === 0) return;
- const mode = getHideMode();
- posts.forEach((post) => {
- const h4 = post.querySelector('.poster h4');
- if (!h4) return;
- // Store original name and avatar once
- if (!post.dataset.blfOriginalName) {
- post.dataset.blfOriginalName = h4.textContent.trim();
- }
- const avatarImg = post.querySelector('.poster img.avatar');
- if (avatarImg && !post.dataset.blfOriginalAvatar) {
- post.dataset.blfOriginalAvatar = avatarImg.src;
- }
- const originalName = post.dataset.blfOriginalName;
- const blocked = isBlocked(originalName);
- // Remove old show buttons
- post.querySelectorAll('.blf-show-btn').forEach((b) => b.remove());
- if (blocked) {
- if (mode === 'hide') {
- // Completely hide the post
- post.classList.remove('blf-censored');
- post.classList.add('blf-hidden');
- // Restore originals in case switching from censor mode
- restorePost(post, h4, avatarImg);
- } else {
- // Censor mode
- post.classList.remove('blf-hidden');
- post.classList.add('blf-censored');
- // Replace username display
- const link = h4.querySelector('a');
- if (link) {
- if (!link.dataset.blfOriginalText) link.dataset.blfOriginalText = link.textContent;
- link.textContent = 'Blocked User';
- } else {
- if (!h4.dataset.blfOriginalText) h4.dataset.blfOriginalText = h4.textContent;
- h4.textContent = 'Blocked User';
- }
- // Replace avatar with generic silhouette, match original size
- if (avatarImg) {
- if (!avatarImg.dataset.blfOriginalWidth) {
- avatarImg.dataset.blfOriginalWidth = avatarImg.width || 75;
- avatarImg.dataset.blfOriginalHeight = avatarImg.height || 75;
- }
- avatarImg.src = GENERIC_AVATAR;
- avatarImg.style.width = avatarImg.dataset.blfOriginalWidth + 'px';
- avatarImg.style.height = avatarImg.dataset.blfOriginalHeight + 'px';
- }
- // Add show/hide toggle
- const keyinfo = post.querySelector('.keyinfo');
- if (keyinfo) {
- const showBtn = document.createElement('button');
- showBtn.className = 'blf-show-btn';
- showBtn.textContent = 'Show Post';
- showBtn.addEventListener('click', () => {
- if (post.classList.contains('blf-censored')) {
- post.classList.remove('blf-censored');
- restorePost(post, h4, avatarImg);
- showBtn.textContent = 'Hide Post';
- } else {
- post.classList.add('blf-censored');
- const a = h4.querySelector('a');
- if (a) a.textContent = 'Blocked User';
- else h4.textContent = 'Blocked User';
- if (avatarImg) {
- avatarImg.src = GENERIC_AVATAR;
- avatarImg.style.width = (avatarImg.dataset.blfOriginalWidth || 75) + 'px';
- avatarImg.style.height = (avatarImg.dataset.blfOriginalHeight || 75) + 'px';
- }
- showBtn.textContent = 'Show Post';
- }
- });
- keyinfo.appendChild(showBtn);
- }
- }
- } else {
- post.classList.remove('blf-censored');
- post.classList.remove('blf-hidden');
- restorePost(post, h4, avatarImg);
- }
- });
- }
- function restorePost(post, h4, avatarImg) {
- const link = h4.querySelector('a');
- if (link && link.dataset.blfOriginalText) link.textContent = link.dataset.blfOriginalText;
- else if (h4.dataset.blfOriginalText) h4.textContent = h4.dataset.blfOriginalText;
- if (avatarImg && post.dataset.blfOriginalAvatar) {
- avatarImg.src = post.dataset.blfOriginalAvatar;
- avatarImg.style.width = '';
- avatarImg.style.height = '';
- }
- }
- // Add "Block User" links under each poster in topic view
- function addBlockLinks() {
- const posts = document.querySelectorAll('div.windowbg, div.windowbg2');
- posts.forEach((post) => {
- const poster = post.querySelector('.poster');
- if (!poster || poster.querySelector('.blf-block-link')) return;
- const h4 = poster.querySelector('h4');
- if (!h4) return;
- const blockLink = document.createElement('span');
- blockLink.className = 'blf-block-link';
- blockLink.textContent = 'Block User';
- blockLink.addEventListener('click', () => {
- const originalName = post.dataset.blfOriginalName || h4.textContent.trim();
- addToBlocklist(originalName);
- });
- poster.appendChild(blockLink);
- });
- }
- // ==============================================
- // 2) BOARD VIEW: Filter/censor topics in listing
- // ==============================================
- // Structure: table.table_grid > tr > td.subject
- // td.subject > div > span (topic link) + p ("Started by" <a>username</a>)
- function filterTopics() {
- const table = document.querySelector('table.table_grid');
- if (!table) return;
- const mode = getHideMode();
- const rows = table.querySelectorAll('tbody tr');
- rows.forEach((row) => {
- const subjectCell = row.querySelector('td.subject');
- if (!subjectCell) return;
- const startedByP = subjectCell.querySelector('p');
- if (!startedByP) return;
- // Find the "Started by" author link
- const authorLink = startedByP.querySelector('a');
- if (!authorLink) return;
- // Only match the first link (the author), not page number links inside <small>
- const small = startedByP.querySelector('small');
- if (small && small.contains(authorLink)) return;
- // Get first <a> that is a direct child or not inside <small>
- let realAuthorLink = null;
- for (const a of startedByP.querySelectorAll('a')) {
- if (!small || !small.contains(a)) {
- realAuthorLink = a;
- break;
- }
- }
- if (!realAuthorLink) return;
- if (!row.dataset.blfOriginalAuthor) {
- row.dataset.blfOriginalAuthor = realAuthorLink.textContent.trim();
- }
- const originalAuthor = row.dataset.blfOriginalAuthor;
- const blocked = isBlocked(originalAuthor);
- // Remove old toggle buttons
- row.querySelectorAll('.blf-topic-show-btn').forEach((b) => b.remove());
- if (blocked) {
- if (mode === 'hide') {
- row.classList.remove('blf-topic-censored');
- row.classList.add('blf-topic-hidden');
- if (realAuthorLink.dataset.blfOriginalText) {
- realAuthorLink.textContent = realAuthorLink.dataset.blfOriginalText;
- }
- } else {
- row.classList.remove('blf-topic-hidden');
- row.classList.add('blf-topic-censored');
- if (!realAuthorLink.dataset.blfOriginalText) {
- realAuthorLink.dataset.blfOriginalText = realAuthorLink.textContent;
- }
- realAuthorLink.textContent = 'Blocked User';
- // Add a small show toggle
- const showBtn = document.createElement('button');
- showBtn.className = 'blf-topic-show-btn';
- showBtn.textContent = 'Show';
- showBtn.addEventListener('click', (e) => {
- e.preventDefault();
- e.stopPropagation();
- if (row.classList.contains('blf-topic-censored')) {
- row.classList.remove('blf-topic-censored');
- if (realAuthorLink.dataset.blfOriginalText) {
- realAuthorLink.textContent = realAuthorLink.dataset.blfOriginalText;
- }
- showBtn.textContent = 'Hide';
- } else {
- row.classList.add('blf-topic-censored');
- realAuthorLink.textContent = 'Blocked User';
- showBtn.textContent = 'Show';
- }
- });
- startedByP.appendChild(showBtn);
- }
- } else {
- row.classList.remove('blf-topic-censored');
- row.classList.remove('blf-topic-hidden');
- if (realAuthorLink.dataset.blfOriginalText) {
- realAuthorLink.textContent = realAuthorLink.dataset.blfOriginalText;
- }
- }
- });
- }
- // =====================================================
- // 3) BOARD INDEX: Censor "Last post by" blocked users
- // =====================================================
- // Structure: td.lastpost > p > "Last post" <strong> ... "by" <a>username</a> "in" <a>topic</a>
- function filterBoardIndex() {
- const lastpostCells = document.querySelectorAll('td.lastpost');
- if (lastpostCells.length === 0) return;
- const mode = getHideMode();
- lastpostCells.forEach((cell) => {
- const p = cell.querySelector('p');
- if (!p) return;
- // Find the "by" author link — it's the <a> right after text containing "by"
- let authorLink = null;
- const childNodes = Array.from(p.childNodes);
- for (let i = 0; i < childNodes.length; i++) {
- const node = childNodes[i];
- if (node.nodeType === 3 && node.textContent.includes('by')) {
- // Next sibling element should be the author link
- const next = childNodes[i + 1];
- if (next && next.tagName === 'A') {
- authorLink = next;
- break;
- }
- }
- }
- if (!authorLink) return;
- if (!cell.dataset.blfOriginalAuthor) {
- cell.dataset.blfOriginalAuthor = authorLink.textContent.trim();
- }
- const originalAuthor = cell.dataset.blfOriginalAuthor;
- const blocked = isBlocked(originalAuthor);
- if (blocked) {
- if (mode === 'hide') {
- p.classList.add('blf-lastpost-censored');
- if (!authorLink.dataset.blfOriginalText) {
- authorLink.dataset.blfOriginalText = authorLink.textContent;
- }
- authorLink.textContent = 'Blocked User';
- } else {
- p.classList.add('blf-lastpost-censored');
- if (!authorLink.dataset.blfOriginalText) {
- authorLink.dataset.blfOriginalText = authorLink.textContent;
- }
- authorLink.textContent = 'Blocked User';
- }
- } else {
- p.classList.remove('blf-lastpost-censored');
- if (authorLink.dataset.blfOriginalText) {
- authorLink.textContent = authorLink.dataset.blfOriginalText;
- }
- }
- });
- }
- // =====================================================
- // 4) TOPIC LISTING: Censor "last post by" in td.lastpost
- // =====================================================
- // Structure on board pages: td.lastpost > ... text "by" <a>username</a> (no <p> wrapper)
- function filterTopicLastPosts() {
- const table = document.querySelector('table.table_grid');
- if (!table) return;
- const lastpostCells = table.querySelectorAll('td.lastpost');
- lastpostCells.forEach((cell) => {
- // Skip if already handled by filterBoardIndex (has <p> wrapper)
- if (cell.querySelector('p')) return;
- let authorLink = null;
- const childNodes = Array.from(cell.childNodes);
- for (let i = 0; i < childNodes.length; i++) {
- const node = childNodes[i];
- if (node.nodeType === 3 && node.textContent.includes('by')) {
- const next = childNodes[i + 1];
- if (next && next.tagName === 'A') {
- authorLink = next;
- break;
- }
- }
- }
- if (!authorLink) return;
- if (!cell.dataset.blfOriginalAuthor) {
- cell.dataset.blfOriginalAuthor = authorLink.textContent.trim();
- }
- const originalAuthor = cell.dataset.blfOriginalAuthor;
- const blocked = isBlocked(originalAuthor);
- if (blocked) {
- cell.classList.add('blf-lastpost-censored');
- if (!authorLink.dataset.blfOriginalText) {
- authorLink.dataset.blfOriginalText = authorLink.textContent;
- }
- authorLink.textContent = 'Blocked User';
- } else {
- cell.classList.remove('blf-lastpost-censored');
- if (authorLink.dataset.blfOriginalText) {
- authorLink.textContent = authorLink.dataset.blfOriginalText;
- }
- }
- });
- }
- // =====================================================
- // 5) QUOTES: Censor quotes from blocked users
- // =====================================================
- // Structure: .quoteheader > div > a with text "Quote from: USERNAME on DATE"
- // followed by blockquote.bbc_standard_quote
- function filterQuotes() {
- const quoteHeaders = document.querySelectorAll('.quoteheader');
- if (quoteHeaders.length === 0) return;
- const mode = getHideMode();
- quoteHeaders.forEach((qh) => {
- const div = qh.querySelector('div');
- if (!div) return;
- const link = div.querySelector('a');
- // Use stored original or current text to extract username
- const text = (link && link.dataset.blfOriginalText)
- ? link.dataset.blfOriginalText
- : (link ? link.textContent.trim() : div.textContent.trim());
- // Extract username from "Quote from: USERNAME on DATE"
- const match = text.match(/^Quote from:\s+(.+?)\s+on\s+/);
- if (!match) return;
- const quotedUser = match[1];
- // Store original link text once
- if (link && !link.dataset.blfOriginalText) {
- link.dataset.blfOriginalText = link.textContent;
- }
- const blockquote = qh.nextElementSibling;
- const isQuoteBq = blockquote && blockquote.classList.contains('bbc_standard_quote');
- const blocked = isBlocked(quotedUser);
- if (blocked) {
- if (mode === 'hide') {
- qh.style.display = 'none';
- if (isQuoteBq) blockquote.style.display = 'none';
- qh.classList.remove('blf-quote-censored');
- if (isQuoteBq) blockquote.classList.remove('blf-quote-censored');
- } else {
- qh.style.display = '';
- if (isQuoteBq) blockquote.style.display = '';
- qh.classList.add('blf-quote-censored');
- if (isQuoteBq) blockquote.classList.add('blf-quote-censored');
- if (link) link.textContent = 'Quote from: Blocked User';
- }
- } else {
- qh.style.display = '';
- if (isQuoteBq) blockquote.style.display = '';
- qh.classList.remove('blf-quote-censored');
- if (isQuoteBq) blockquote.classList.remove('blf-quote-censored');
- if (link && link.dataset.blfOriginalText) {
- link.textContent = link.dataset.blfOriginalText;
- }
- }
- });
- }
- // --- Tampermonkey Menu Command ---
- GM_registerMenuCommand('Edit Blocklist', createBlocklistPanel);
- // --- Add a [Blocklist] button to the forum nav ---
- function addNavButton() {
- const dropmenu = document.querySelector('#main_menu .dropmenu');
- if (dropmenu && !dropmenu.querySelector('.blf-nav-btn')) {
- // Build the same structure as native nav items: li > a.firstlevel > span.firstlevel
- const li = document.createElement('li');
- const btn = document.createElement('a');
- btn.className = 'firstlevel blf-nav-btn';
- btn.href = '#';
- const span = document.createElement('span');
- span.className = 'firstlevel';
- span.textContent = 'Blocklist';
- btn.appendChild(span);
- btn.addEventListener('click', (e) => {
- e.preventDefault();
- createBlocklistPanel();
- });
- li.appendChild(btn);
- // Insert before the last direct child nav item (Logout/Register)
- const directLis = Array.from(dropmenu.children).filter((c) => c.tagName === 'LI');
- const lastLi = directLis[directLis.length - 1];
- if (lastLi) {
- dropmenu.insertBefore(li, lastLi);
- } else {
- dropmenu.appendChild(li);
- }
- return;
- }
- // Fallback: navigate_section breadcrumb area
- const navSec = document.querySelector('.navigate_section');
- if (navSec && !navSec.querySelector('.blf-nav-btn')) {
- const btn = document.createElement('a');
- btn.className = 'blf-nav-btn';
- btn.textContent = 'Blocklist';
- btn.href = '#';
- btn.style.cssText = 'margin: 0 8px 0 0;';
- btn.addEventListener('click', (e) => {
- e.preventDefault();
- createBlocklistPanel();
- });
- navSec.appendChild(btn);
- }
- }
- // --- Run all filters ---
- function runAll() {
- filterPosts();
- addBlockLinks();
- filterQuotes();
- filterTopics();
- filterTopicLastPosts();
- filterBoardIndex();
- }
- // --- Init ---
- addNavButton();
- runAll();
- })();
Add Comment
Please, Sign In to add comment