Guest User

Untitled

a guest
Jan 8th, 2026
157
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.67 KB | None | 0 0
  1. // ==UserScript==
  2. // @name AutoAdmit User Hider
  3. // @namespace http://tampermonkey.net/
  4. // @version 2.0
  5. // @description Hide threads and posts from specific users on AutoAdmit
  6. // @match *://www.autoadmit.com/*
  7. // @match *://autoadmit.com/*
  8. // @match *://www.xoxohth.com/*
  9. // @match *://xoxohth.com/*
  10. // @grant none
  11. // ==/UserScript==
  12.  
  13. (function() {
  14. 'use strict';
  15.  
  16. // ============ CONFIGURATION ============
  17. const BLOCKED_USERS = [
  18. 'https://i.imgur.com/3so5uWV.jpeg'
  19. // Add more usernames here
  20. ];
  21.  
  22. const FETCH_DELAY_MS = 500; // Delay between requests to avoid rate limiting
  23. const CACHE_EXPIRY_DAYS = 1; // How long to cache thread author data
  24. // ========================================
  25.  
  26. const CACHE_KEY = 'autoadmit_thread_authors';
  27. const CACHE_TIME_KEY = 'autoadmit_cache_times';
  28.  
  29. // Load cached data
  30. function getCache() {
  31. try {
  32. return JSON.parse(localStorage.getItem(CACHE_KEY) || '{}');
  33. } catch {
  34. return {};
  35. }
  36. }
  37.  
  38. function getCacheTimes() {
  39. try {
  40. return JSON.parse(localStorage.getItem(CACHE_TIME_KEY) || '{}');
  41. } catch {
  42. return {};
  43. }
  44. }
  45.  
  46. function saveCache(cache) {
  47. localStorage.setItem(CACHE_KEY, JSON.stringify(cache));
  48. }
  49.  
  50. function saveCacheTimes(times) {
  51. localStorage.setItem(CACHE_TIME_KEY, JSON.stringify(times));
  52. }
  53.  
  54. function isCacheExpired(threadId) {
  55. const times = getCacheTimes();
  56. if (!times[threadId]) return true;
  57. const expiryMs = CACHE_EXPIRY_DAYS * 24 * 60 * 60 * 1000;
  58. return (Date.now() - times[threadId]) > expiryMs;
  59. }
  60.  
  61. function escapeRegex(string) {
  62. return string.replace(/[.*+?^${}()|[\]\\\/]/g, '\\$&');
  63. }
  64.  
  65. function isBlockedUser(username) {
  66. if (!username) return false;
  67. const lowerUsername = username.toLowerCase().trim();
  68. return BLOCKED_USERS.some(blocked =>
  69. lowerUsername === blocked.toLowerCase().trim()
  70. );
  71. }
  72.  
  73. // Fetch a thread page and extract the OP's username
  74. async function fetchThreadAuthor(threadId) {
  75. try {
  76. const response = await fetch(`/thread.php?thread_id=${threadId}&forum_id=2`);
  77. const html = await response.text();
  78.  
  79. // Parse the HTML to find the first author
  80. const parser = new DOMParser();
  81. const doc = parser.parseFromString(html, 'text/html');
  82.  
  83. // Find first post table (width=700, not indented)
  84. const tables = doc.querySelectorAll('table[width="700"]');
  85. for (const table of tables) {
  86. // Check if this is a top-level post (no indentation td)
  87. const firstTd = table.querySelector('td:first-child');
  88. if (firstTd && firstTd.querySelector('img[src*="blank.gif"]')) {
  89. continue; // This is a reply (indented)
  90. }
  91.  
  92. // Extract author from this table
  93. const tableHtml = table.innerHTML;
  94. const authorMatch = tableHtml.match(/<b>Author:<\/b>(?:&nbsp;|\s)*(?:<[^>]*>)*\s*([^<]+)/i);
  95. if (authorMatch) {
  96. return authorMatch[1].trim();
  97. }
  98. }
  99. return null;
  100. } catch (error) {
  101. console.error(`Error fetching thread ${threadId}:`, error);
  102. return null;
  103. }
  104. }
  105.  
  106. // Get all thread IDs from the main page
  107. function getThreadIds() {
  108. const threadIds = [];
  109. const links = document.querySelectorAll('a[href*="thread_id="]');
  110. links.forEach(link => {
  111. const match = link.href.match(/thread_id=(\d+)/);
  112. if (match) {
  113. threadIds.push({
  114. id: match[1],
  115. row: link.closest('tr')
  116. });
  117. }
  118. });
  119. // Remove duplicates
  120. const seen = new Set();
  121. return threadIds.filter(item => {
  122. if (seen.has(item.id)) return false;
  123. seen.add(item.id);
  124. return true;
  125. });
  126. }
  127.  
  128. // Hide a thread row
  129. function hideThreadRow(row) {
  130. if (row) {
  131. row.style.display = 'none';
  132. }
  133. }
  134.  
  135. // Process threads on main page
  136. async function processMainPage() {
  137. const threads = getThreadIds();
  138. const cache = getCache();
  139. const cacheTimes = getCacheTimes();
  140.  
  141. let fetchCount = 0;
  142. const toFetch = [];
  143.  
  144. // First pass: hide already-cached blocked threads, identify what needs fetching
  145. for (const thread of threads) {
  146. if (cache[thread.id] && !isCacheExpired(thread.id)) {
  147. if (isBlockedUser(cache[thread.id])) {
  148. hideThreadRow(thread.row);
  149. }
  150. } else {
  151. toFetch.push(thread);
  152. }
  153. }
  154.  
  155. // Show status
  156. let statusEl = document.getElementById('aa-hider-status');
  157. if (!statusEl && toFetch.length > 0) {
  158. statusEl = document.createElement('div');
  159. statusEl.id = 'aa-hider-status';
  160. statusEl.style.cssText = 'position:fixed;top:10px;right:10px;background:#333;color:#fff;padding:10px;border-radius:5px;z-index:9999;font-size:12px;';
  161. document.body.appendChild(statusEl);
  162. }
  163.  
  164. // Fetch unknown threads
  165. for (let i = 0; i < toFetch.length; i++) {
  166. const thread = toFetch[i];
  167.  
  168. if (statusEl) {
  169. statusEl.textContent = `Scanning threads: ${i + 1}/${toFetch.length}`;
  170. }
  171.  
  172. const author = await fetchThreadAuthor(thread.id);
  173. if (author) {
  174. cache[thread.id] = author;
  175. cacheTimes[thread.id] = Date.now();
  176.  
  177. // Save immediately after each fetch
  178. saveCache(cache);
  179. saveCacheTimes(cacheTimes);
  180.  
  181. if (isBlockedUser(author)) {
  182. hideThreadRow(thread.row);
  183. }
  184. }
  185.  
  186. // Delay between requests
  187. if (i < toFetch.length - 1) {
  188. await new Promise(resolve => setTimeout(resolve, FETCH_DELAY_MS));
  189. }
  190. }
  191.  
  192. // Remove status
  193. if (statusEl) {
  194. statusEl.textContent = 'Done!';
  195. setTimeout(() => statusEl.remove(), 2000);
  196. }
  197. }
  198.  
  199. // Hide posts within thread pages
  200. function hidePostsInThread() {
  201. const tables = document.querySelectorAll('table[width="700"]');
  202. tables.forEach(table => {
  203. const tableHtml = table.innerHTML;
  204. for (const blockedUser of BLOCKED_USERS) {
  205. const authorPattern = new RegExp(
  206. `<b>Author:<\\/b>(?:&nbsp;|\\s)*(?:<[^>]*>)*\\s*${escapeRegex(blockedUser)}`,
  207. 'i'
  208. );
  209. if (authorPattern.test(tableHtml)) {
  210. table.style.display = 'none';
  211. let prev = table.previousElementSibling;
  212. while (prev && (prev.tagName === 'BR' || prev.tagName === 'A' || prev.tagName === 'P')) {
  213. prev.style.display = 'none';
  214. prev = prev.previousElementSibling;
  215. }
  216. break;
  217. }
  218. }
  219. });
  220.  
  221. // Hide from thread summary at top
  222. const summaryTds = document.querySelectorAll('table[cellpadding="0"][cellspacing="0"] td');
  223. summaryTds.forEach(td => {
  224. for (const blockedUser of BLOCKED_USERS) {
  225. if (td.textContent.includes(blockedUser)) {
  226. let parent = td.parentElement;
  227. if (parent) parent.style.display = 'none';
  228. }
  229. }
  230. });
  231. }
  232.  
  233. // Determine if we're on main page or thread page
  234. function isMainPage() {
  235. return window.location.pathname.includes('main.php') ||
  236. (window.location.pathname === '/' && !window.location.search.includes('thread_id'));
  237. }
  238.  
  239. function isThreadPage() {
  240. return window.location.search.includes('thread_id') ||
  241. window.location.pathname.includes('thread.php');
  242. }
  243.  
  244. // Main execution
  245. if (isMainPage()) {
  246. processMainPage();
  247. }
  248.  
  249. if (isThreadPage()) {
  250. hidePostsInThread();
  251. }
  252.  
  253. // Also run on pages that might be both (like forum listings)
  254. if (!isMainPage() && !isThreadPage()) {
  255. // Try both approaches
  256. hidePostsInThread();
  257. }
  258.  
  259. })();
Advertisement
Add Comment
Please, Sign In to add comment