Flying OC Alert

Alerts you when you want to fly but an OC is about to start.

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

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name         Flying OC Alert
// @namespace    http://tampermonkey.net/
// @version      1.1.0
// @description  Alerts you when you want to fly but an 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';

    let apiKey = localStorage.getItem("nichtgersti-flying-oc-alert-apikey") ?? '###PDA-APIKEY###' //Minimal access or above!
    let maxWarningHours = localStorage.getItem("nichtgersti-flying-oc-alert-max-warning-hours") ?? 10
    let alertOption = Number.parseInt(localStorage.getItem("nichtgersti-flying-oc-alert-alert-option")) ?? 0 //0 -> simple alert; 1 -> confirm prompt; 2 confirm math question
    let confirmMessage = localStorage.getItem("nichtgersti-flying-oc-alert-confirm-message") ?? "continue" //for confirmPrompt

    let alertOptionsMenuId
    let confirmMessageMenuId

    try {
        GM_registerMenuCommand('Set Api Key', setApiKey)
        GM_registerMenuCommand('Set Max Warning Hours', setMaxWarningHours)
        if (alertOption == 1) confirmMessageMenuId = GM_registerMenuCommand('Set Confirm Message', setConfirmMessage)
        setAlertOption(alertOption)
    } catch (error) {
        console.warn('[Flying OC Alert] Tampermonkey not detected!')
    }

    setApiKey(true)

    let ocUrl = "https://api.torn.com/v2/user/?selections=organizedcrime&key={apiKey}".replace("{apiKey}", apiKey)

    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 totalSeconds = infoOc.ready_at - Math.floor(Date.now() / 1000)
        if (totalSeconds / 3600 > 10) return

        let days = Math.floor(totalSeconds / 86400) % 24
        let hours = Math.floor(totalSeconds / 3600) % 60
        let minutes = Math.floor(totalSeconds / 60) % 60
        let seconds = totalSeconds % 60

        let timeString = ""
        if (totalSeconds > 86400) timeString += `${(days < 10) ? "0" : ""}${days}:`
        if (totalSeconds > 3600) timeString += `${(hours < 10) ? "0" : ""}${hours}:`
        if (totalSeconds > 60) timeString += `${(minutes < 10) ? "0" : ""}${minutes}:`
        timeString += `${(seconds < 10) ? "0" : ""}${seconds}`
        if (totalSeconds < 60) timeString = `${(seconds < 10) ? "0" : ""}${seconds} seconds`

        let message
        let randomNumber1 = Math.ceil((Math.random() * 50))
        let randomNumber2 = Math.ceil((Math.random() * 50))
        let correctAnswer = (randomNumber1 + randomNumber2).toString()
        switch (alertOption) {
            case 0:
                alert(`Your Organzied Crime is about to start:\n${timeString}`)
                break
            case 1:
                while (message != confirmMessage) message = prompt(`Your Organzied Crime is about to start:\n${timeString}\nWrite "${confirmMessage}" to continue.`)
                break
            case 2:
                while (message != correctAnswer) message = prompt(`Your Organzied Crime is about to start:\n${timeString}\nSolve "${randomNumber1} + ${randomNumber2}" to continue.`)
                break
            default:
                console.log(alertOption)
                throw new Error('Something went wrong');
        }
    })
    .catch(error => console.error("[Flying OC Alert] Error:", error))

    function setApiKey(checkExisting = false) {
        if (!checkExisting || apiKey === null || apiKey.indexOf('PDA-APIKEY') > -1 || apiKey.length != 16){
            let userInput = prompt("Please enter a minimal access API key.", apiKey ?? '')
            if (userInput !== null && userInput.length == 16) {
                apiKey = userInput
                localStorage.setItem("nichtgersti-flying-oc-alert-apikey", apiKey)
            }
        }
    }

    function setMaxWarningHours() {
        let userInput = prompt("Please enter the maximum time in hours you want to get warned at.", maxWarningHours ?? '10')
        if (userInput !== null) {
            try {
                maxWarningHours = Number.parseFloat(userInput)
                localStorage.setItem("nichtgersti-flying-oc-alert-max-warning-hours", maxWarningHours)
            } catch (error) { alert("Not a valid input") }
        }
    }

    function setAlertOption(option = (alertOption + 1) % 3) {
        alertOption = option
        localStorage.setItem("nichtgersti-flying-oc-alert-alert-option", alertOption)
        let optionText = ["Simple Alert", "Confirmation Prompt", "Confirmation Addition"]
        try {
            GM_unregisterMenuCommand(alertOptionsMenuId)
            GM_unregisterMenuCommand(confirmMessageMenuId)
        } catch (error) { console.log(error) }
        try {
            alertOptionsMenuId = GM_registerMenuCommand(optionText[option], function() {setAlertOption()})
            if (alertOption == 1) confirmMessageMenuId = GM_registerMenuCommand('Set Confirm Message', setConfirmMessage)
        } catch (error) { throw error }
        return option
    }

    function setConfirmMessage() {
        let userInput = prompt("Please enter what you want to type out to confirm that you have been alerted.", confirmMessage ?? '10')
        if (userInput !== null) {
            try {
                confirmMessage = userInput
                localStorage.setItem("nichtgersti-flying-oc-alert-confirm-message", confirmMessage)
            } catch (error) { alert("Not a valid input") }
        }
    }

})();