Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // ==UserScript==
- // @name AutoAdmit User Hider 2
- // @namespace http://tampermonkey.net/
- // @version 2.0
- // @description Hide threads and posts from specific users on AutoAdmit
- // @match *://www.autoadmit.com/*
- // @match *://autoadmit.com/*
- // @match *://www.xoxohth.com/*
- // @match *://xoxohth.com/*
- // @grant none
- // ==/UserScript==
- (function() {
- 'use strict';
- // ============ CONFIGURATION ============
- const DEFAULT_BLOCKED_USERS = [
- 'https://imgur.com/a/o2g8xYK'
- // Add more usernames here
- ];
- const FETCH_DELAY_MS = 500; // Delay between requests to avoid rate limiting
- const CACHE_EXPIRY_DAYS = 1; // How long to cache thread author data
- // ========================================
- const CACHE_KEY = 'autoadmit_thread_authors';
- const CACHE_TIME_KEY = 'autoadmit_cache_times';
- const BLOCKED_USERS_KEY = 'autoadmit_blocked_users';
- // Get blocked users (combines default + user-added)
- function getBlockedUsers() {
- try {
- const userAdded = JSON.parse(localStorage.getItem(BLOCKED_USERS_KEY) || '[]');
- return [...DEFAULT_BLOCKED_USERS, ...userAdded];
- } catch {
- return [...DEFAULT_BLOCKED_USERS];
- }
- }
- function getUserAddedBlocklist() {
- try {
- return JSON.parse(localStorage.getItem(BLOCKED_USERS_KEY) || '[]');
- } catch {
- return [];
- }
- }
- function saveUserBlocklist(list) {
- localStorage.setItem(BLOCKED_USERS_KEY, JSON.stringify(list));
- }
- function addBlockedUser(username) {
- const list = getUserAddedBlocklist();
- const trimmed = username.trim();
- if (trimmed && !list.some(u => u.toLowerCase() === trimmed.toLowerCase())) {
- list.push(trimmed);
- saveUserBlocklist(list);
- return true;
- }
- return false;
- }
- function removeBlockedUser(username) {
- const list = getUserAddedBlocklist();
- const filtered = list.filter(u => u.toLowerCase() !== username.toLowerCase());
- saveUserBlocklist(filtered);
- }
- // Create the UI
- function createBlocklistUI() {
- // Container
- const container = document.createElement('div');
- container.id = 'aa-blocklist-container';
- container.style.cssText = 'position:fixed;bottom:10px;right:10px;z-index:9999;font-family:Arial,sans-serif;font-size:12px;';
- // Toggle button
- const toggleBtn = document.createElement('button');
- toggleBtn.textContent = '🚫';
- toggleBtn.style.cssText = 'background:#444;color:#fff;border:none;padding:2px 4px;border-radius:5px;cursor:pointer;';
- container.appendChild(toggleBtn);
- // Panel (hidden by default)
- const panel = document.createElement('div');
- panel.style.cssText = 'display:none;background:#333;color:#fff;padding:10px;border-radius:5px;margin-top:5px;width:250px;max-height:300px;overflow-y:auto;';
- // Input row
- const inputRow = document.createElement('div');
- inputRow.style.cssText = 'display:flex;gap:5px;margin-bottom:10px;';
- const input = document.createElement('input');
- input.type = 'text';
- input.placeholder = 'Enter username...';
- input.style.cssText = 'flex:1;padding:5px;border:none;border-radius:3px;';
- const addBtn = document.createElement('button');
- addBtn.textContent = 'Add';
- addBtn.style.cssText = 'background:#5a5;color:#fff;border:none;padding:5px 10px;border-radius:3px;cursor:pointer;';
- inputRow.appendChild(input);
- inputRow.appendChild(addBtn);
- panel.appendChild(inputRow);
- // List container
- const listContainer = document.createElement('div');
- listContainer.id = 'aa-blocklist-list';
- panel.appendChild(listContainer);
- container.appendChild(panel);
- document.body.appendChild(container);
- // Render the list
- function renderList() {
- const allBlocked = getBlockedUsers();
- const userAdded = getUserAddedBlocklist();
- listContainer.innerHTML = '';
- if (allBlocked.length === 0) {
- listContainer.innerHTML = '<div style="color:#999;">No blocked users</div>';
- return;
- }
- allBlocked.forEach(username => {
- const row = document.createElement('div');
- row.style.cssText = 'display:flex;justify-content:space-between;align-items:center;padding:5px;background:#444;margin-bottom:3px;border-radius:3px;';
- const nameSpan = document.createElement('span');
- nameSpan.textContent = username;
- nameSpan.style.cssText = 'overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:180px;';
- nameSpan.title = username;
- row.appendChild(nameSpan);
- // Only show remove button for user-added entries
- const isUserAdded = userAdded.some(u => u.toLowerCase() === username.toLowerCase());
- if (isUserAdded) {
- const removeBtn = document.createElement('button');
- removeBtn.textContent = '✕';
- removeBtn.style.cssText = 'background:#a55;color:#fff;border:none;padding:2px 6px;border-radius:3px;cursor:pointer;font-size:10px;';
- removeBtn.onclick = () => {
- removeBlockedUser(username);
- renderList();
- };
- row.appendChild(removeBtn);
- } else {
- const defaultBadge = document.createElement('span');
- defaultBadge.textContent = 'default';
- defaultBadge.style.cssText = 'font-size:9px;color:#999;';
- row.appendChild(defaultBadge);
- }
- listContainer.appendChild(row);
- });
- }
- // Toggle panel visibility
- toggleBtn.onclick = () => {
- const isVisible = panel.style.display !== 'none';
- panel.style.display = isVisible ? 'none' : 'block';
- if (!isVisible) renderList();
- };
- // Add user
- function addUser() {
- if (addBlockedUser(input.value)) {
- input.value = '';
- renderList();
- // Refresh the page to apply new blocks
- if (confirm('User added. Reload page to apply changes?')) {
- location.reload();
- }
- }
- }
- addBtn.onclick = addUser;
- input.onkeypress = (e) => {
- if (e.key === 'Enter') addUser();
- };
- }
- // Initialize UI
- createBlocklistUI();
- // Load cached data
- function getCache() {
- try {
- return JSON.parse(localStorage.getItem(CACHE_KEY) || '{}');
- } catch {
- return {};
- }
- }
- function getCacheTimes() {
- try {
- return JSON.parse(localStorage.getItem(CACHE_TIME_KEY) || '{}');
- } catch {
- return {};
- }
- }
- function saveCache(cache) {
- localStorage.setItem(CACHE_KEY, JSON.stringify(cache));
- }
- function saveCacheTimes(times) {
- localStorage.setItem(CACHE_TIME_KEY, JSON.stringify(times));
- }
- function isCacheExpired(threadId) {
- const times = getCacheTimes();
- if (!times[threadId]) return true;
- const expiryMs = CACHE_EXPIRY_DAYS * 24 * 60 * 60 * 1000;
- return (Date.now() - times[threadId]) > expiryMs;
- }
- function escapeRegex(string) {
- return string.replace(/[.*+?^${}()|[\]\\\/]/g, '\\$&');
- }
- function isBlockedUser(username) {
- if (!username) return false;
- const lowerUsername = username.toLowerCase().trim();
- const blockedUsers = getBlockedUsers();
- return blockedUsers.some(blocked =>
- lowerUsername === blocked.toLowerCase().trim()
- );
- }
- // Fetch a thread page and extract the OP's username
- async function fetchThreadAuthor(threadId) {
- try {
- const response = await fetch(`/thread.php?thread_id=${threadId}&forum_id=2`);
- const html = await response.text();
- // Parse the HTML to find the first author
- const parser = new DOMParser();
- const doc = parser.parseFromString(html, 'text/html');
- // Find first post table (width=700, not indented)
- const tables = doc.querySelectorAll('table[width="700"]');
- for (const table of tables) {
- // Check if this is a top-level post (no indentation td)
- const firstTd = table.querySelector('td:first-child');
- if (firstTd && firstTd.querySelector('img[src*="blank.gif"]')) {
- continue; // This is a reply (indented)
- }
- // Extract author from this table
- const tableHtml = table.innerHTML;
- const authorMatch = tableHtml.match(/<b>Author:<\/b>(?: |\s)*(?:<[^>]*>)*\s*([^<]+)/i);
- if (authorMatch) {
- return authorMatch[1].trim();
- }
- }
- return null;
- } catch (error) {
- console.error(`Error fetching thread ${threadId}:`, error);
- return null;
- }
- }
- // Get all thread IDs from the main page
- function getThreadIds() {
- const threadIds = [];
- const links = document.querySelectorAll('a[href*="thread_id="]');
- links.forEach(link => {
- const match = link.href.match(/thread_id=(\d+)/);
- if (match) {
- threadIds.push({
- id: match[1],
- row: link.closest('tr')
- });
- }
- });
- // Remove duplicates
- const seen = new Set();
- return threadIds.filter(item => {
- if (seen.has(item.id)) return false;
- seen.add(item.id);
- return true;
- });
- }
- // Hide a thread row
- function hideThreadRow(row) {
- if (row) {
- row.style.display = 'none';
- }
- }
- // Process threads on main page
- async function processMainPage() {
- const threads = getThreadIds();
- const cache = getCache();
- const cacheTimes = getCacheTimes();
- let fetchCount = 0;
- const toFetch = [];
- // First pass: hide already-cached blocked threads, identify what needs fetching
- for (const thread of threads) {
- if (cache[thread.id] && !isCacheExpired(thread.id)) {
- if (isBlockedUser(cache[thread.id])) {
- hideThreadRow(thread.row);
- }
- } else {
- toFetch.push(thread);
- }
- }
- // Show status
- let statusEl = document.getElementById('aa-hider-status');
- if (!statusEl && toFetch.length > 0) {
- statusEl = document.createElement('div');
- statusEl.id = 'aa-hider-status';
- statusEl.style.cssText = 'position:fixed;top:10px;right:10px;background:#333;color:#fff;padding:10px;border-radius:5px;z-index:9999;font-size:12px;';
- document.body.appendChild(statusEl);
- }
- // Fetch unknown threads
- for (let i = 0; i < toFetch.length; i++) {
- const thread = toFetch[i];
- if (statusEl) {
- statusEl.textContent = `Scanning threads: ${i + 1}/${toFetch.length}`;
- }
- const author = await fetchThreadAuthor(thread.id);
- if (author) {
- cache[thread.id] = author;
- cacheTimes[thread.id] = Date.now();
- // Save immediately after each fetch
- saveCache(cache);
- saveCacheTimes(cacheTimes);
- if (isBlockedUser(author)) {
- hideThreadRow(thread.row);
- }
- }
- // Delay between requests
- if (i < toFetch.length - 1) {
- await new Promise(resolve => setTimeout(resolve, FETCH_DELAY_MS));
- }
- }
- // Remove status
- if (statusEl) {
- statusEl.textContent = 'Done!';
- setTimeout(() => statusEl.remove(), 2000);
- }
- }
- // Hide posts within thread pages
- function hidePostsInThread() {
- const blockedUsers = getBlockedUsers();
- const tables = document.querySelectorAll('table[width="700"]');
- tables.forEach(table => {
- const tableHtml = table.innerHTML;
- for (const blockedUser of blockedUsers) {
- const authorPattern = new RegExp(
- `<b>Author:<\\/b>(?: |\\s)*(?:<[^>]*>)*\\s*${escapeRegex(blockedUser)}`,
- 'i'
- );
- if (authorPattern.test(tableHtml)) {
- table.style.display = 'none';
- let prev = table.previousElementSibling;
- while (prev && (prev.tagName === 'BR' || prev.tagName === 'A' || prev.tagName === 'P')) {
- prev.style.display = 'none';
- prev = prev.previousElementSibling;
- }
- break;
- }
- }
- });
- // Hide from thread summary at top
- const summaryTds = document.querySelectorAll('table[cellpadding="0"][cellspacing="0"] td');
- summaryTds.forEach(td => {
- for (const blockedUser of blockedUsers) {
- if (td.textContent.includes(blockedUser)) {
- let parent = td.parentElement;
- if (parent) parent.style.display = 'none';
- }
- }
- });
- }
- // Determine if we're on main page or thread page
- function isMainPage() {
- return window.location.pathname.includes('main.php') ||
- (window.location.pathname === '/' && !window.location.search.includes('thread_id'));
- }
- function isThreadPage() {
- return window.location.search.includes('thread_id') ||
- window.location.pathname.includes('thread.php');
- }
- // Main execution
- if (isMainPage()) {
- processMainPage();
- }
- if (isThreadPage()) {
- hidePostsInThread();
- }
- // Also run on pages that might be both (like forum listings)
- if (!isMainPage() && !isThreadPage()) {
- // Try both approaches
- hidePostsInThread();
- }
- })();
Advertisement
Add Comment
Please, Sign In to add comment