Shoplifting alert

Display a red square if cameras or guards are down in Big Al's. Clicking the red square removes notification for 30 minutes.

当前为 2023-09-09 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Shoplifting alert
  3. // @namespace http://torn.city.com.dot.com.com
  4. // @version 1.4.4
  5. // @description Display a red square if cameras or guards are down in Big Al's. Clicking the red square removes notification for 30 minutes.
  6. // @author Adobi
  7. // @match *://*/*
  8. // @grant GM_setValue
  9. // @grant GM_getValue
  10. // @license MIT
  11. // ==/UserScript==
  12.  
  13. (function() {
  14. 'use strict';
  15.  
  16. ///////////////////////////////// USER DEFINED VARIABLES /////////////////////////////////
  17.  
  18. const timeOut = 1800 * 1000 // 30 minute time out when you click red square. Change if you want.
  19. const copyCat = false // Set to true if you want a message put in your clipboard when you click the red square.
  20. // Purpose of message is to paste in faction chat to notify your friends that they should shoplift.
  21. // Message below, change as you wish.
  22. const copyMessage = "Lacking security at Big Al's - shoplift now for special ammo https://www.torn.com/loader.php?sid=crimes#/shoplifting"
  23.  
  24. ////////// END OF USER DEFINED VARIABLES. Change things below at your own risk. //////////
  25.  
  26.  
  27. // Function to create and display yellow square with the option to enter API key
  28. function displayYellowSquare() {
  29. const yellowSquare = document.createElement('div');
  30. yellowSquare.id = 'yellowSquare';
  31. yellowSquare.style.position = 'fixed';
  32. yellowSquare.style.left = '0';
  33. yellowSquare.style.top = '0';
  34. yellowSquare.style.width = '100px';
  35. yellowSquare.style.height = '100px';
  36. yellowSquare.style.backgroundColor = 'yellow';
  37. yellowSquare.style.zIndex = '99999999';
  38. yellowSquare.style.display = 'flex'; // Use flexbox for centering
  39. yellowSquare.style.cursor = 'pointer'; // Change cursor to pointer
  40.  
  41. // Create a container div for centered text
  42. const textContainer = document.createElement('div');
  43. textContainer.style.margin = 'auto'; // Center horizontally
  44. textContainer.style.textAlign = 'center'; // Center text
  45. textContainer.style.display = 'flex';
  46. textContainer.style.flexDirection = 'column'; // Center vertically
  47.  
  48. // Create text nodes for the yellow square with a line break
  49. const yellowTextNode0 = document.createTextNode('Shoplift alerter');
  50. const lineBreak = document.createElement('br');
  51. const yellowTextNode1 = document.createTextNode('Click here to');
  52. const lineBreak2 = document.createElement('br');
  53. const yellowTextNode2 = document.createTextNode('supply API key');
  54.  
  55.  
  56. // Append the text nodes and line break to the text container
  57. textContainer.appendChild(yellowTextNode0);
  58. textContainer.appendChild(lineBreak);
  59. textContainer.appendChild(yellowTextNode1);
  60. textContainer.appendChild(lineBreak2);
  61. textContainer.appendChild(yellowTextNode2);
  62.  
  63. // Append the text container to the yellow square
  64. yellowSquare.appendChild(textContainer);
  65.  
  66. // Append the yellow square to the body (if it's not already added)
  67. if (!document.getElementById('yellowSquare')) {
  68. document.body.appendChild(yellowSquare);
  69. }
  70.  
  71. // Add a click event listener to the yellow square
  72. yellowSquare.addEventListener('click', () => {
  73. const apiKey = prompt('Enter your API key:');
  74. if (apiKey) {
  75. // Store the API key with GM_setValue
  76. GM_setValue('shoplifting_api_key', apiKey);
  77. yellowSquare.remove(); // Remove the yellow square after entering the API key
  78. fetchAndDisplayData(); // Run an API call with the new key
  79. }
  80. });
  81. }
  82.  
  83. // Check if the API key is already stored using GM_getValue
  84. const apiKey = GM_getValue('shoplifting_api_key', '');
  85.  
  86. // If the API key is not stored, display the yellow square
  87. if (!apiKey) {
  88. displayYellowSquare();
  89. }
  90.  
  91. // Function to create and display the red square text, and remove it if security is back up
  92. function displayRedSquare(camera, guard) {
  93. const existingRedSquare = document.getElementById('redSquare');
  94. if (existingRedSquare) {
  95. existingRedSquare.remove();
  96. }
  97. // Check if both camera and guard values are false
  98. if (camera === false && guard === false) {
  99. // If both are false, remove the red square div (if it exists)
  100. const existingRedSquare = document.getElementById('redSquare');
  101. if (existingRedSquare) {
  102. existingRedSquare.remove();
  103. }
  104. return; // Exit the function, as there's no need to create the red square
  105. }
  106.  
  107. // Create or update the red square div
  108. const redSquare = document.getElementById('redSquare') || document.createElement('div');
  109. redSquare.id = 'redSquare';
  110. redSquare.style.position = 'fixed';
  111. redSquare.style.left = '0';
  112. redSquare.style.top = '0';
  113. redSquare.style.width = '100px';
  114. redSquare.style.height = '100px';
  115. redSquare.style.backgroundColor = 'red';
  116. redSquare.style.zIndex = '99999999';
  117. redSquare.style.display = 'flex'; // Use flexbox for centering
  118.  
  119. // Create a container div for centered text
  120. const textContainer = document.createElement('div');
  121. textContainer.style.margin = 'auto'; // Center horizontally
  122. textContainer.style.textAlign = 'center'; // Center text
  123. textContainer.style.display = 'flex';
  124. textContainer.style.flexDirection = 'column'; // Center vertically
  125.  
  126. // Create text nodes for "camera" and "guard" values
  127. let cameraTextNode = document.createTextNode(`Camera: Online`);
  128. let guardTextNode = document.createTextNode(`Guards: On duty`);
  129. if (camera) { cameraTextNode = document.createTextNode(`Camera: Offline`); }
  130. if (guard) { guardTextNode = document.createTextNode(`Guards: Gone`); }
  131. const lineBreak = document.createElement('br');
  132.  
  133. // Append the text nodes and line break to the text container
  134. textContainer.appendChild(cameraTextNode);
  135. textContainer.appendChild(lineBreak);
  136. textContainer.appendChild(guardTextNode);
  137.  
  138. // Append the text container to the red square
  139. redSquare.appendChild(textContainer);
  140.  
  141. // Append the red square to the body (if it's not already added)
  142. if (!document.getElementById('redSquare')) {
  143. document.body.appendChild(redSquare);
  144. }
  145.  
  146. // Add a click event listener to the red square
  147. redSquare.addEventListener('click', () => {
  148. // Put a message into clipboard for easy pasting to faction chat, if copyCat is enabled
  149. if (copyCat === true) {
  150. navigator.clipboard.writeText(copyMessage)
  151. }
  152. // Set camera and guard values to false
  153. GM_setValue('cameraValue', false);
  154. GM_setValue('guardValue', false);
  155.  
  156. // Set the timestamp to the current timestamp plus a time defined by the user at the top of this script
  157. GM_setValue('lastCallTime', Date.now() + timeOut);
  158.  
  159. // Remove the red square div
  160. redSquare.remove();
  161. });
  162. }
  163.  
  164. // Function to fetch API data and display the red square
  165. function fetchAndDisplayData() {
  166. const currentTime = Date.now();
  167. const lastCallTime = GM_getValue('lastCallTime', 0);
  168. // Check if at least 60 seconds have passed since the last API call
  169. if (currentTime - lastCallTime >= 60000) {
  170.  
  171. // Check if the API key is already stored using GM_getValue
  172. const apiKey = GM_getValue('shoplifting_api_key', '');
  173. // If the API key is not stored, display the yellow square
  174. if (!apiKey) {
  175. displayYellowSquare();
  176. }
  177.  
  178. fetch(`https://api.torn.com/torn/?selections=shoplifting&key=${apiKey}`)
  179. .then(response => response.json())
  180. .then(data => {
  181. // Check if there's an error in the API response
  182. if (data.error && data.error.error === "Incorrect key") {
  183. GM_setValue('shoplifting_api_key', "");
  184. displayYellowSquare();
  185. } else {
  186. // Get the values for "camera" and "guard" from the API data
  187. const camera = data.shoplifting.big_als[0].disabled;
  188. const guard = data.shoplifting.big_als[1].disabled;
  189.  
  190. // Store the values of "camera" and "guard"
  191. GM_setValue('cameraValue', camera);
  192. GM_setValue('guardValue', guard);
  193. GM_setValue('lastCallTime', currentTime); // Store the current timestamp
  194.  
  195. // Call the displayRedSquare function with camera and guard values
  196. displayRedSquare(camera, guard);
  197. }
  198. })
  199. .catch(error => console.error('there was an API Error:', error));
  200. }
  201. }
  202.  
  203. // Initial run after 2 seconds with saved values of camera and guard, or fetch new data if values don't exist
  204. setTimeout(() => {
  205. const currentTime = Date.now();
  206. const lastCallTime = GM_getValue('lastCallTime', 0);
  207. // Check if the last saved timestamp is more than 60 seconds ago or if cameraValue and guardValue don't exist
  208. if (
  209. currentTime - lastCallTime >= 60000 ||
  210. GM_getValue('cameraValue') === undefined ||
  211. GM_getValue('guardValue') === undefined
  212. ) {
  213. // If any of the conditions are met, fetch new data
  214. fetchAndDisplayData();
  215. } else {
  216. // Otherwise, use the old saved values for camera and guard
  217. const savedCamera = GM_getValue('cameraValue', false); // Default to false if not saved
  218. const savedGuard = GM_getValue('guardValue', false); // Default to false if not saved
  219. displayRedSquare(savedCamera, savedGuard);
  220. }
  221. }, 2000);
  222.  
  223. // Repeat every 10 seconds
  224. setInterval(fetchAndDisplayData, 10000);
  225. //displayYellowSquare() //debugging
  226. //displayRedSquare(true, false) //debugging
  227. })();