您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Blocks you from flying if your OC is about to start.
当前为
// ==UserScript== // @name Flying OC Alert // @namespace http://tampermonkey.net/ // @version 2.0.3 // @description Blocks you from flying if your OC is about to start. // @author NichtGersti [3380912] // @license MIT // @match https://www.torn.com/page.php?sid=travel // @icon https://www.google.com/s2/favicons?sz=64&domain=torn.com // @grant GM_registerMenuCommand // @grant GM_unregisterMenuCommand // ==/UserScript== (function() { 'use strict'; window.addEventListener('load', () => { let potentialError = document.querySelector("#skip-to-content")?.textContent?.trim() if (potentialError == Error) { console.warn("[Flying OC Alert] You're probably racing. Aborting."); return; } let apiKey = localStorage.getItem("nichtgersti-flying-oc-alert-api-key") ?? '###PDA-APIKEY###'; //Minimal access or above! let threshold = localStorage.getItem("nichtgersti-flying-oc-alert-threshold") ?? 10; let confirmMethod = localStorage.getItem("nichtgersti-flying-oc-alert-method") ?? "default"; let confirmPrompt = localStorage.getItem("nichtgersti-flying-oc-alert-prompt") ?? "continue"; let ocUrl = "https://api.torn.com/v2/user/?selections=organizedcrime&key={apiKey}".replace("{apiKey}", apiKey); let solution = Math.floor(Math.random() * 100); let addend1 = Math.floor(Math.random() * (solution - 1)); let addend2 = Math.floor(solution - addend1); let confirmTask = undefined; let confirmData = undefined; if (confirmMethod == "prompt") { confirmTask = confirmPrompt; confirmData = confirmPrompt; } else if (confirmMethod == "addition") { confirmTask = `${addend1}+${addend2}`; confirmData = solution.toString(); } let alertDiv = document.createElement("div"); alertDiv.id = "flying-oc-alert"; alertDiv.classList.add("info-msg-cont", "border-round", "m-top10", "green"); alertDiv.innerHTML = ` <div class="info-msg border-round messageWrap___phpSP"> <i class="infoIcon___GLFcq"></i> <div class="delimiter"> <div class="msg right-round messageContent___LhCmx"> <div style="display:flex;justify-content: space-between;align-items: center;"> <span style="display:inline-block;vertical-align:middle">Time until your Organized Crime is ready: <span id="flying-oc-alert-timer">Check your API key.</span></span> <div id="flying-oc-settings-button" class="btn torn-btn btn-action-tab btn-dark-bg" style="display:inline-block;float:right"> Settings </div> </div> <div id="flying-oc-confirm-div" hidden> ${buildConfirm(confirmMethod, confirmTask, confirmData)} </div> <div id="flying-oc-settings" hidden> ${buildSettings()} </div> </div> </div> </div> `; let wrapper = document.querySelector("#travel-root .wrapper"); wrapper.insertBefore(alertDiv, wrapper.lastChild); let confirmButton = document.querySelector("#flying-oc-confirm-button"); confirmButton.addEventListener("click", () => pressConfirm()); let settingsButton = document.querySelector("#flying-oc-settings-button"); settingsButton.addEventListener("click", () => openSettings()); let settingsSaveButton = document.querySelector("#flying-oc-settings-save-button"); settingsSaveButton.addEventListener("click", () => saveSettings()); fetch(ocUrl).then( response => { if (response.ok) { return response.json(); } throw new Error('Something went wrong'); }) .then( result => { if (result.error) { switch (result.error.code){ case 2: apiKey = null; localStorage.setItem("nichtgersti-flying-oc-alert-api", null); console.error("[Flying OC Alert] Incorrect Api Key:", result); return; case 9: console.warn("[Flying OC Alert] The API is temporarily disabled, please try again later"); return; default: console.error("[Flying OC Alert] Error:", result.error.error); return; } } let infoOc = result.organizedCrime; let timeString; if (!infoOc || infoOc.status != "Planning") { timeString = "You're currently not planning an Organized Crime."; document.querySelector("#flying-oc-alert-timer").textContent = timeString; return; } let totalSeconds = infoOc.ready_at - Math.floor(Date.now() / 1000); if ((totalSeconds / 3600) < threshold) { document.querySelector("#flying-oc-alert").classList.add("red"); document.querySelector("#flying-oc-alert").classList.remove("green"); document.querySelector("#flying-oc-confirm-div").hidden = false; setHideFlying(true); } timeString = createTimerString(totalSeconds); document.querySelector("#flying-oc-alert-timer").textContent = createTimerString(totalSeconds); setInterval((function() { let seconds = infoOc.ready_at - Math.floor(Date.now() / 1000); document.querySelector("#flying-oc-alert-timer").textContent = createTimerString(seconds); }), 10000); }) .catch(error => console.error("[Flying OC Alert] Error:", error)); function setHideFlying(hide = true) { let travelTypeSelector = document.querySelector(".travelTypeSelector___zK5N4") || undefined; if (travelTypeSelector && hide) travelTypeSelector.style.display = "none"; else if (travelTypeSelector) travelTypeSelector.style.removeProperty("display"); let worldMap = document.querySelector(".worldMap___SvXMZ") || undefined; if (worldMap && hide) worldMap.style.display = "none"; else if (worldMap) worldMap.style.removeProperty("display"); let destinationPanel = document.querySelector(".destinationPanel___LsJ4v") || undefined; if (destinationPanel && hide) destinationPanel.style.display = "none"; else if (destinationPanel) destinationPanel.style.removeProperty("display"); let destinationList = document.querySelector(".destinationList___fx7Gb") || undefined; if (destinationList && hide) destinationList.style.display = "none"; else if (destinationList) destinationList.style.removeProperty("display"); } function createTimerString(totalSeconds) { if (totalSeconds < 0) { return `Your OC is being delayed by someone else!`; } if (totalSeconds < 60) { return `Less than 1 minute!`; } let days = Math.floor(totalSeconds / 86400); let hours = Math.floor(totalSeconds / 3600) % 24; let minutes = Math.floor(totalSeconds / 60) % 60; let seconds = totalSeconds % 60; let timerString = ""; if (totalSeconds > 86400) timerString += `${days}d `; if (totalSeconds > 3600) timerString += `${hours}h `; if (totalSeconds > 60) timerString += `${minutes}m`; return timerString; } function buildConfirm(method = confirmMethod, task = undefined, data = undefined) { let confirmText = "Confirm to unlock traveling."; if (method == "prompt") confirmText = `Write "${task}" to confirm.`; else if (method == "addition") confirmText = `Solve "${task}" to confirm.`; return ` <hr style="margin-top:10px;margin-bottom:10px"> <div style="display:flex;justify-content: space-between;align-items: center;"> <span style="display:inline-block;vertical-align:middle">${confirmText}</span> <div style="display:flex;justify-content: space-between;"> <input type="text" id="flying-oc-confirm-input" name="flying-oc-confirm-input"${method == "default" ? " hidden" : ""} data="${data}"> <div id="flying-oc-confirm-button" class="btn torn-btn btn-action-tab btn-dark-bg"> Confirm </div> </div> </div> `; } function buildSettings() { return ` <hr style="margin-top:10px;margin-bottom:10px"> <div style="display:flex;justify-content: space-between;align-items: center;"> <div style="display:inline-block;vertical-align:middle"> <label for="flying-oc-api-key">API Key (Minimal Access):</label> <input type="text" id="flying-oc-api-key" name="flying-oc-api-key" value="${apiKey}"><br><br> <label for="flying-oc-threshold">Threshold (in hours):</label> <input type="text" id="flying-oc-threshold" name="flying-oc-threshold" value="${threshold}"><br><br> <label for="flying-oc-method">Confirmation Method:</label> <select id="flying-oc-method" name="flying-oc-method"> <option value="default"${confirmMethod == "default" ? " selected" : ""}>Default</option> <option value="prompt"${confirmMethod == "prompt" ? " selected" : ""}>Prompt</option> <option value="addition"${confirmMethod == "addition" ? " selected" : ""}>Addition</option> </select><br><br> <label for="flying-oc-prompt">Confirmation Prompt (only if "Prompt" is selected):</label> <input type="text" id="flying-oc-prompt" name="flying-oc-confirm-prompt" value="${confirmPrompt}"> </div> <div id="flying-oc-settings-save-button" class="btn torn-btn btn-action-tab btn-dark-bg" style="display:inline-block;float:right"> Save </div> </div> ` }; function openSettings(open = !document.querySelector("#flying-oc-settings").hidden) { document.querySelector("#flying-oc-settings").hidden = open; } function saveSettings() { let newApiKey = document.querySelector("#flying-oc-api-key").value; if (newApiKey.length == 16) { apiKey = newApiKey; localStorage.setItem("nichtgersti-flying-oc-alert-api-key", apiKey); } else document.querySelector("#flying-oc-api-key").value = apiKey; let newThreshold = Number.parseInt(document.querySelector("#flying-oc-threshold").value); if (newThreshold) { threshold = newThreshold; localStorage.setItem("nichtgersti-flying-oc-alert-threshold", threshold); } else document.querySelector("#flying-oc-threshold").value = threshold; confirmMethod = document.querySelector("#flying-oc-method").selectedOptions[0].value; localStorage.setItem("nichtgersti-flying-oc-alert-method", confirmMethod); confirmPrompt = document.querySelector("#flying-oc-prompt").value; localStorage.setItem("nichtgersti-flying-oc-alert-prompt", confirmPrompt); console.log("[Flying OC Alert] Settings saved."); } function pressConfirm() { let confirmInput = document.querySelector("#flying-oc-confirm-input"); if (confirmInput.getAttribute("data") != "undefined" && confirmInput.value != confirmInput.getAttribute("data")) return; setHideFlying(false); document.querySelector("#flying-oc-confirm-div").hidden = true; } }) })();