您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Display a red square if cameras or guards are down in Big Al's. Clicking the red square removes notification for 30 minutes.
// ==UserScript== // @name Shoplifting alert // @namespace http://torn.city.com.dot.com.com // @version 1.4.6.1 // @description Display a red square if cameras or guards are down in Big Al's. Clicking the red square removes notification for 30 minutes. // @author Adobi // @match *://*/* // @grant GM_setValue // @grant GM_getValue // @license MIT // ==/UserScript== (function() { 'use strict'; ///////////////////////////////// USER DEFINED VARIABLES ///////////////////////////////// const timeOut = 1800 * 1000 // 30 minute time out when you click red square. Change if you want. const copyCat = true // Set to true if you want a message put in your clipboard when you click the red square. // Purpose of message is to paste in faction chat to notify your friends that they should shoplift. // Message below, change as you wish. const baseMessage = "Shoplift now for special ammo https://www.torn.com/loader.php?sid=crimes#/shoplifting" const guardsDown = "Guards are gone at Big Al's - " const camerasDown = "Cameras are down at Big Al's - " const bothDown = "Cameras AND guards are down at Big Al's, holy shit - " ////////// END OF USER DEFINED VARIABLES. Change things below at your own risk. ////////// // Function to create and display yellow square with the option to enter API key function displayYellowSquare() { const yellowSquare = document.createElement('div'); yellowSquare.id = 'yellowSquare'; yellowSquare.style.position = 'fixed'; yellowSquare.style.left = '0'; yellowSquare.style.top = '0'; yellowSquare.style.width = '100px'; yellowSquare.style.height = '100px'; yellowSquare.style.backgroundColor = 'yellow'; yellowSquare.style.zIndex = '99999999'; yellowSquare.style.display = 'flex'; // Use flexbox for centering yellowSquare.style.cursor = 'pointer'; // Change cursor to pointer // Create a container div for centered text const textContainer = document.createElement('div'); textContainer.style.margin = 'auto'; // Center horizontally textContainer.style.textAlign = 'center'; // Center text textContainer.style.display = 'flex'; textContainer.style.flexDirection = 'column'; // Center vertically // Create text nodes for the yellow square with a line break const yellowTextNode0 = document.createTextNode('Shoplift alerter'); const lineBreak = document.createElement('br'); const yellowTextNode1 = document.createTextNode('Click here to'); const lineBreak2 = document.createElement('br'); const yellowTextNode2 = document.createTextNode('supply API key'); // Append the text nodes and line break to the text container textContainer.appendChild(yellowTextNode0); textContainer.appendChild(lineBreak); textContainer.appendChild(yellowTextNode1); textContainer.appendChild(lineBreak2); textContainer.appendChild(yellowTextNode2); // Append the text container to the yellow square yellowSquare.appendChild(textContainer); // Append the yellow square to the body (if it's not already added) if (!document.getElementById('yellowSquare')) { document.body.appendChild(yellowSquare); } // Add a click event listener to the yellow square yellowSquare.addEventListener('click', () => { const apiKey = prompt('Enter your API key:'); if (apiKey) { // Store the API key with GM_setValue GM_setValue('shoplifting_api_key', apiKey); yellowSquare.remove(); // Remove the yellow square after entering the API key fetchAndDisplayData(); // Run an API call with the new key } }); } // Check if the API key is already stored using GM_getValue const apiKey = GM_getValue('shoplifting_api_key', ''); // If the API key is not stored, display the yellow square if (!apiKey) { displayYellowSquare(); } // Function to create and display the red square text, and remove it if security is back up function displayRedSquare(camera, guard) { const existingRedSquare = document.getElementById('redSquare'); if (existingRedSquare) { existingRedSquare.remove(); } // Check if both camera and guard values are false if (camera === false && guard === false) { return; // Exit the function, as there's no need to create the red square } const currentTime = GM_getValue('lastCallTime', 0) if (GM_getValue('timeOut',0) > currentTime) { if (camera === false || guard === false) { return; } } // Create or update the red square div const redSquare = document.getElementById('redSquare') || document.createElement('div'); redSquare.id = 'redSquare'; redSquare.style.position = 'fixed'; redSquare.style.left = '0'; redSquare.style.top = '0'; redSquare.style.width = '100px'; redSquare.style.height = '100px'; redSquare.style.backgroundColor = 'red'; redSquare.style.zIndex = '99999999'; redSquare.style.display = 'flex'; // Use flexbox for centering // Create a container div for centered text const textContainer = document.createElement('div'); textContainer.style.margin = 'auto'; // Center horizontally textContainer.style.textAlign = 'center'; // Center text textContainer.style.display = 'flex'; textContainer.style.flexDirection = 'column'; // Center vertically // Create text nodes for "camera" and "guard" values let cameraTextNode = document.createTextNode(`Camera: Online`); let guardTextNode = document.createTextNode(`Guards: On duty`); if (camera) { cameraTextNode = document.createTextNode(`Camera: Offline`); } if (guard) { guardTextNode = document.createTextNode(`Guards: Gone`); } const lineBreak = document.createElement('br'); // Append the text nodes and line break to the text container textContainer.appendChild(cameraTextNode); textContainer.appendChild(lineBreak); textContainer.appendChild(guardTextNode); // Append the text container to the red square redSquare.appendChild(textContainer); // Append the red square to the body (if it's not already added) if (!document.getElementById('redSquare')) { document.body.appendChild(redSquare); } // Add a click event listener to the red square redSquare.addEventListener('click', () => { // Put a message into clipboard for easy pasting to faction chat, if copyCat is enabled if (copyCat === true) { let copyMessage = ""; if (camera === true && guard === true) { copyMessage = bothDown + baseMessage; } else { if (guard === true) { copyMessage = guardsDown + baseMessage; } else { copyMessage = camerasDown + baseMessage; } } navigator.clipboard.writeText(copyMessage) } // Set camera and guard values to false GM_setValue('cameraValue', false); GM_setValue('guardValue', false); // Set the timestamp to the current timestamp plus a time defined by the user at the top of this script GM_setValue('timeOut', Date.now() + timeOut); // Remove the red square div redSquare.remove(); }); } // Function to fetch API data and display the red square function fetchAndDisplayData() { const currentTime = Date.now(); const lastCallTime = GM_getValue('lastCallTime', 0); // Check if at least 60 seconds have passed since the last API call if (currentTime - lastCallTime >= 60000) { // Check if the API key is already stored using GM_getValue const apiKey = GM_getValue('shoplifting_api_key', ''); // If the API key is not stored, display the yellow square if (!apiKey) { displayYellowSquare(); } fetch(`https://api.torn.com/torn/?selections=shoplifting&key=${apiKey}`) .then(response => response.json()) .then(data => { // Check if there's an error in the API response if (data.error && data.error.error === "Incorrect key") { GM_setValue('shoplifting_api_key', ""); displayYellowSquare(); } else { // Get the values for "camera" and "guard" from the API data const camera = data.shoplifting.big_als[0].disabled; const guard = data.shoplifting.big_als[1].disabled; // Store the values of "camera" and "guard" GM_setValue('cameraValue', camera); GM_setValue('guardValue', guard); GM_setValue('lastCallTime', currentTime); // Store the current timestamp // Call the displayRedSquare function with camera and guard values displayRedSquare(camera, guard); } }) .catch(error => console.error('there was an API Error:', error)); } } // Initial run after 2 seconds with saved values of camera and guard, or fetch new data if values don't exist setTimeout(() => { const currentTime = Date.now(); const lastCallTime = GM_getValue('lastCallTime', 0); // Check if the last saved timestamp is more than 60 seconds ago or if cameraValue and guardValue don't exist if ( currentTime - lastCallTime >= 60000 || GM_getValue('cameraValue') === undefined || GM_getValue('guardValue') === undefined ) { // If any of the conditions are met, fetch new data fetchAndDisplayData(); } else { // Otherwise, use the old saved values for camera and guard const savedCamera = GM_getValue('cameraValue', false); // Default to false if not saved const savedGuard = GM_getValue('guardValue', false); // Default to false if not saved displayRedSquare(savedCamera, savedGuard); } }, 1); // Repeat every 10 seconds setInterval(fetchAndDisplayData, 10000); //displayYellowSquare() //debugging //displayRedSquare(true, true) //debugging })();