Add Hide and Unhide Button with Trade Filter

Adds "Hide" and "Unhide" buttons, filters trades, and tells you have hidden the user in the trade.

目前為 2025-01-26 提交的版本,檢視 最新版本

  1. // ==UserScript==
  2. // @name Add Hide and Unhide Button with Trade Filter
  3. // @namespace http://tampermonkey.net/
  4. // @version 1.0
  5. // @description Adds "Hide" and "Unhide" buttons, filters trades, and tells you have hidden the user in the trade.
  6. // @author Grance [3487987]
  7. // @match *://*.torn.com/*
  8. // @grant none
  9. // @license MIT
  10. // ==/UserScript==
  11.  
  12. (function () {
  13. 'use strict';
  14.  
  15. // Utility to wait for an element to load
  16. function waitForElement(selector, callback, interval = 100, timeout = 10000) {
  17. const start = Date.now();
  18. const check = setInterval(() => {
  19. const element = document.querySelector(selector);
  20. if (element) {
  21. clearInterval(check);
  22. callback(element);
  23. } else if (Date.now() - start > timeout) {
  24. clearInterval(check);
  25. console.error(`Timeout waiting for element: ${selector}`);
  26. }
  27. }, interval);
  28. }
  29.  
  30. // Function to create the "Hide" button
  31. function createHideButton(userId) {
  32. const buttonsList = document.querySelector('.buttons-list');
  33. if (!buttonsList || document.getElementById('button-hide')) return; // Prevent duplicates
  34. const hideButton = document.createElement('a');
  35. hideButton.id = 'button-hide';
  36. hideButton.href = '#';
  37. hideButton.className = 'profile-button profile-button-hide clickable';
  38. hideButton.setAttribute('aria-label', 'Hide');
  39. hideButton.innerHTML = `
  40. <svg xmlns="http://www.w3.org/2000/svg" class="default___XXAGt profileButtonIcon svgShadowWhiteFilter___Nse17"
  41. fill="rgba(153, 153, 153, 0.4)" stroke="#d4d4d4" stroke-width="2" width="36" height="40" viewBox="0 0 46 46" style="display: block; margin: auto;">
  42. <g transform="translate(1, 1)">
  43. <circle cx="22" cy="25" r="20" fill="none" stroke="black" stroke-width="2"/>
  44. <line x1="12" y1="15" x2="32" y2="35" stroke="black" stroke-width="2"/>
  45. </g>
  46. </svg>
  47. `;
  48.  
  49. // Add click event for hiding the user
  50. hideButton.addEventListener('click', (event) => {
  51. event.preventDefault();
  52. const hiddenList = JSON.parse(localStorage.getItem('hiddenUsers')) || [];
  53. if (!hiddenList.includes(userId)) {
  54. hiddenList.push(userId);
  55. localStorage.setItem('hiddenUsers', JSON.stringify(hiddenList));
  56. alert(`User ${userId} has been hidden.`);
  57. replaceWithUnhideButton(userId); // Replace the button with "Unhide"
  58. }
  59. });
  60.  
  61. return hideButton;
  62. }
  63.  
  64. // Function to create the "Unhide" button
  65. function createUnhideButton(userId) {
  66. const buttonsList = document.querySelector('.buttons-list');
  67. if (!buttonsList || document.getElementById('button-unhide')) return; // Prevent duplicates
  68. const unhideButton = document.createElement('a');
  69. unhideButton.id = 'button-unhide';
  70. unhideButton.href = '#';
  71. unhideButton.className = 'profile-button profile-button-unhide clickable';
  72. unhideButton.setAttribute('aria-label', 'Unhide');
  73. unhideButton.innerHTML = `
  74. <svg xmlns="http://www.w3.org/2000/svg" class="default___XXAGt profileButtonIcon svgShadowWhiteFilter___Nse17"
  75. fill="rgba(153, 153, 153, 0.4)" stroke="#d4d4d4" stroke-width="2" width="40" height="45" viewBox="0 0 46 46" style="display: block; margin: auto;">
  76. <g transform="translate(1, 1)">
  77. <circle cx="22" cy="20" r="20" fill="none" stroke="black" stroke-width="2"/>
  78. <line x1="1" y1="20" x2="41" y2="20" stroke="black" stroke-width="2"/> <!-- Horizontal line -->
  79. </g>
  80. </svg>
  81. `;
  82.  
  83. // Add click event for unhiding the user
  84. unhideButton.addEventListener('click', (event) => {
  85. event.preventDefault();
  86. const hiddenList = JSON.parse(localStorage.getItem('hiddenUsers')) || [];
  87. const index = hiddenList.indexOf(userId);
  88. if (index !== -1) {
  89. hiddenList.splice(index, 1);
  90. localStorage.setItem('hiddenUsers', JSON.stringify(hiddenList));
  91. alert(`User ${userId} has been unhidden.`);
  92. replaceWithHideButton(userId); // Replace the button with "Hide"
  93. }
  94. });
  95.  
  96. return unhideButton;
  97. }
  98.  
  99. // Function to replace the button with "Unhide"
  100. function replaceWithUnhideButton(userId) {
  101. const buttonsList = document.querySelector('.buttons-list');
  102. if (!buttonsList) return;
  103.  
  104. const existingButton = document.getElementById('button-hide');
  105. if (existingButton) {
  106. const unhideButton = createUnhideButton(userId);
  107. buttonsList.replaceChild(unhideButton, existingButton);
  108. }
  109. }
  110.  
  111. // Function to replace the button with "Hide"
  112. function replaceWithHideButton(userId) {
  113. const buttonsList = document.querySelector('.buttons-list');
  114. if (!buttonsList) return;
  115.  
  116. const existingButton = document.getElementById('button-unhide');
  117. if (existingButton) {
  118. const hideButton = createHideButton(userId);
  119. buttonsList.replaceChild(hideButton, existingButton);
  120. }
  121. }
  122.  
  123. // Function to add the button to the profile page
  124. function addProfileButton() {
  125. waitForElement('.buttons-list', (buttonsList) => {
  126. // Extract user ID from the profile buttons
  127. const userId = buttonsList.querySelector('a')?.id.split('-')[2];
  128. if (!userId) return;
  129.  
  130. // Check if the user is in the hidden list
  131. const hiddenList = JSON.parse(localStorage.getItem('hiddenUsers')) || [];
  132. if (hiddenList.includes(userId)) {
  133. // Add "Unhide" button
  134. const unhideButton = createUnhideButton(userId);
  135. buttonsList.appendChild(unhideButton);
  136. } else {
  137. // Add "Hide" button
  138. const hideButton = createHideButton(userId);
  139. buttonsList.appendChild(hideButton);
  140. }
  141. });
  142. }
  143. function checkHiddenInTrade() {
  144. const tradeHeader = document.querySelector('h4.left');
  145. if (!tradeHeader || !tradeHeader.textContent.includes('Trade')) return;
  146.  
  147. // Get user ID from the trade page
  148. const userLink = document.querySelector('a.t-blue.h');
  149. const userId = userLink?.href.match(/XID=(\d+)/)?.[1];
  150. if (!userId) return;
  151.  
  152. // Check against the hidden list
  153. const hiddenList = JSON.parse(localStorage.getItem('hiddenUsers')) || [];
  154. if (hiddenList.includes(userId)) {
  155. // Show the warning message
  156. let warningMessage = document.getElementById('hidden-warning');
  157. if (!warningMessage) {
  158. warningMessage = document.createElement('div');
  159. warningMessage.id = 'hidden-warning';
  160. warningMessage.style.color = 'red';
  161. warningMessage.style.fontWeight = 'bold';
  162. warningMessage.style.fontSize = '24px';
  163. warningMessage.textContent = 'YOU HAVE HIDDEN THIS PERSON';
  164. tradeHeader.parentNode.insertBefore(warningMessage, tradeHeader);
  165. }
  166. }
  167. }
  168.  
  169. // Function to filter trades on the trade page
  170. function filterTrades() {
  171. waitForElement('.trades-cont.current', (tradeList) => {
  172. const hiddenList = JSON.parse(localStorage.getItem('hiddenUsers')) || [];
  173. const tradeItems = tradeList.querySelectorAll('li');
  174.  
  175. tradeItems.forEach((tradeItem) => {
  176. const userLink = tradeItem.querySelector('.namet a');
  177. if (userLink) {
  178. const userId = userLink.href.split('XID=')[1];
  179. if (hiddenList.includes(userId)) {
  180. tradeItem.style.display = 'none';
  181. }
  182. }
  183. });
  184. });
  185. }
  186. // Run checks on initial load and dynamically when the DOM updates
  187. function init() {
  188. if (window.location.href.includes('trade.php#step')) {
  189. checkHiddenInTrade(); // Check for hidden users on the trade page
  190. } else if (window.location.href.includes('trade.php')) {
  191. filterTrades(); // Check for hidden users on the trade page
  192. } else if (window.location.href.includes('profiles.php')) {
  193. addProfileButton(); // Check for hidden users on the trade page
  194. }
  195. }
  196.  
  197. // Observe page changes to re-run the script when navigating dynamically
  198. const observer = new MutationObserver(() => {
  199. init();
  200. });
  201.  
  202. observer.observe(document.body, { childList: true, subtree: true });
  203.  
  204. // Run once on script load
  205. init();
  206. })();
  207.