shoplifting-watcher

Watch shoplifting status for players.

当前为 2024-01-13 提交的版本,查看 最新版本

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

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

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         shoplifting-watcher
// @namespace    nodelore.torn.shoplifting-watcher
// @version      0.1
// @description  Watch shoplifting status for players.
// @author       nodelore[2786679]
// @match        https://www.torn.com/*
// @grant        GM_addStyle
// @license      MIT
// ==/UserScript==

(function(){
    'use strict';

    if(window.SHOPLIFTING_WATCHER){
        return;
    }
    window.SHOPLIFTING_WATCHER = true;

    // ============================= Configuration ==============================
    let API = "";
    const CONFIG_STORAGE_KEY = "SHOPLIFTING_WATCHER"
    let watcher_config = {
        interval: 60, // second,
        enabled: []
    }
    // ==========================================================================
    let inPDA = false;
    const PDAKey = "###PDA-APIKEY###";
    if(PDAKey.charAt(0) !== "#"){
        inPDA = true;
        if(!API){
            API = PDAKey;
        }
    }
    if(localStorage.getItem(CONFIG_STORAGE_KEY)){
        watcher_config = JSON.parse(localStorage.getItem(CONFIG_STORAGE_KEY));
    }

    const notify = (notification)=>{
        if(inPDA){
            alert(notification);
            return;
        }
        try{
            if (Notification.permission === "granted") {
                new Notification(notification);
            } 
            else if (Notification.permission !== "denied") {
                Notification.requestPermission().then(function (permission) {
                  if (permission === "granted") {
                    new Notification(notification);
                  }
                });
            }
        } catch(e){
        }

    }

    const update_config = ()=>{
        localStorage.setItem(CONFIG_STORAGE_KEY, JSON.stringify(watcher_config));
    }

    const addStyle = ()=>{
        const styles = `
            .dark-mode #shoplifting-body *{
                color: #000;
            }
            #shoplifting-body{
                display: flex;
                position: fixed;
                width: 300px;
                height: auto;
                background: #FFF;
                border-radius: 6px;
                left: 30px;
                top: 30px;
                box-sizing: border-box;
                padding: 15px;
                flex-flow: column nowrap;
                z-index: 1000000;
            }
            #shoplifting-body.hidden{
                display: none !important;
            }

            .shoplifting-title{
                display: flex;
                flex-flow: row nowrap;
                align-items: center;
                margin-bottom: 15px;
            }

            .shoplifting-title div.heading{
                font-size: 16px;
                font-weight: bold;
            }

            .shoplifting-title div.close-btn{
                margin-left: auto;
            }

            .shoplifting-status{
                width: 100%;
                display: flex;
                flex-flow: column nowrap;
                flex: 1;
            }

            .shoplifting-item{
                width: 100%;
                display: flex;
                border-top: 1px solid rgba(1, 1, 1, .1);
                box-sizing: border-box;
                padding: 10px 0;
                align-items: center;
            }

            .shoplifting-item-info{
                display: flex;
                flex-flow: column nowrap;
            }

            .shoplifting-item-name{
                font-weight: bold;
                font-size: 14px;
            }

            .shoplifting-item-detail-name{
                font-size: 13px;
                margin-top: 5px;
            }

            .shoplifting-item-toggle{
                display: flex;
                margin-left: auto;
                cursor: pointer;
                height: 100%;
            }

            .shoplifting-item-toggle div{
                width: 60px;
                height: 30px;
                line-height: 30px;
                box-shadow: 0 0 6px 3px rgba(1, 1, 1, .1);
                text-align: center;
                font-weight: bold;
                border-radius: 3px;
                color: #FFF;
                transition: .15s all ease-in-out;
                opacity: .3;
            }

            .shoplifting-item-toggle div.active{
                opacity: 1 !important;
            }

            .shoplifting-item-toggle div.active{
                opacity: 1;
            }

            .shoplifting-item-toggle div:hover{
                opacity: 1;
            }

            .shoplifting-item-toggle-on{
                background: #82c91e;
            }

            .shoplifting-item-toggle-off{
                background: #E54C19;
            }

            .shoplifting-apiusage{
                display: flex;
                align-items: center;
                border-top: 1px solid rgba(1, 1, 1, .1);
                box-sizing: border-box;
                padding: 10px 0 0 0;
            }

            .shoplifting-apiusage div{
                font-weight: bold;
                font-size: 14px;
            }
            .shoplifting-apiusage input{
                color: rgba(1, 1, 1, .5);
                height: 20px;
                line-height: 20px;
                margin-left: auto;
                width: 120px;
                background: #F2F2F2;
                text-align: center;
                font-weight: bold;
            }

        `;
        const isTampermonkeyEnabled = typeof unsafeWindow !== 'undefined';
        if (isTampermonkeyEnabled){
            GM_addStyle(styles);
        } else {
            let style = document.createElement("style");
            style.type = "text/css";
            style.innerHTML = styles;
            document.head.appendChild(style);
        }
    }

    addStyle();

    let watcher_interval;
    let icon_interval;
    const insert_icon = ()=>{
        if($("ul[class*=status-icons]").length === 0){
            if(!icon_interval){
                icon_interval = setInterval(()=>{
                    insert_icon();
                    icon_interval = null;
                }, 500)
            }
            return;
        }
        if($("ul[class*=status-icons]").find(".shoplifting_watcher").length === 0){
            const icon = $("<li class='shoplifting_watcher' title='Shoplifting Watcher'></li>");
            icon.css({
                "background-image": "url(/images/v2/editor/emoticons.svg)",
                "cursor": "pointer",
                "background-position": "-74px -42px"
            });
            icon.click(function(){
                if($("div#shoplifting-body").hasClass("hidden")){
                    $("div#shoplifting-body").removeClass("hidden");
                } else{
                    $("div#shoplifting-body").addClass("hidden");
                }
                
            })
            $("ul[class*=status-icons]").prepend(icon);
        }
    }

    const update_watcher = ()=>{
        if(!API){
            return;
        }
        let update_flag = false;
        if($("#shoplifting-body .shoplifting-status div.shoplifting-item").length > 0){
            update_flag = true;
        }
        fetch(`https://api.torn.com/torn/?selections=shoplifting&key=${API}`).then((res)=>{
            if(res.ok){
                res.json().then((data)=>{
                    let notification = "";
                    const shoplifting_data = data["shoplifting"];
                    for(let shop_name in shoplifting_data){
                        const shop_status = shoplifting_data[shop_name];
                        if(!update_flag){
                            let status_detail = `<div class="shoplifting-item-detail">`;
                            for(let detail of shop_status){
                                let prefix = ""
                                if(detail["disabled"]){
                                    prefix = "❌";
                                    if(watcher_config.enabled.indexOf(shop_name) !== -1){
                                        if(notification.length > 0){
                                            notification += "\n";
                                        }
                                        notification += `【${shop_name}】【${detail["title"]}】 is disabled`
                                    }
                                } else{
                                    prefix = "✅";
                                }
                                status_detail += `<div class="shoplifting-item-detail-name" data-security="${detail['title']}">${prefix} ${detail["title"]}</div>`;
                            }
                            status_detail += "</div>";
    
                            const shoplifting_item = $(`
                                <div class="shoplifting-item">
                                    <div class="shoplifting-item-info">
                                        <div class="shoplifting-item-name">${shop_name}</div>
                                        ${status_detail}
                                    </div>
                                </div>
                            `);
    
                            let toggleOn = "";
                            let toggleOff = "";
                            if(watcher_config.enabled.indexOf(shop_name) !== -1){
                                toggleOn = " active";
                            } else{
                                toggleOff = " active";
                            }
                            const toggle = $(`
                                <div class="shoplifting-item-toggle" data-shop="${shop_name}">
                                    <div class="shoplifting-item-toggle-on${toggleOn}">ON</div>
                                    <div class="shoplifting-item-toggle-off${toggleOff}">OFF</div>
                                </div>`
                            );
    
                            toggle.click(function(){
                                const shop = $(this).attr("data-shop");
                                if(watcher_config.enabled.indexOf(shop) !== -1){
                                    watcher_config.enabled.pop(shop);
                                    $(`div.shoplifting-item-toggle[data-shop=${shop}] .shoplifting-item-toggle-off`).addClass("active");
                                    $(`div.shoplifting-item-toggle[data-shop=${shop}] .shoplifting-item-toggle-on`).removeClass("active");
                                } else{
                                    watcher_config.enabled.push(shop);
                                    $(`div.shoplifting-item-toggle[data-shop=${shop}] .shoplifting-item-toggle-off`).removeClass("active");
                                    $(`div.shoplifting-item-toggle[data-shop=${shop}] .shoplifting-item-toggle-on`).addClass("active");
                                }
                                update_config();
                            });
    
                            shoplifting_item.append(toggle);
                            $("#shoplifting-body").find(".shoplifting-status").append(shoplifting_item);
                        }
                        else{
                            for(let detail of shop_status){
                                let prefix = ""
                                if(detail["disabled"]){
                                    prefix = "❌";
                                    if(watcher_config.enabled.indexOf(shop_name) !== -1){
                                        if(notification.length > 0){
                                            notification += "\n";
                                        }
                                        notification += `【${shop_name}】【${detail["title"]}】 is disabled`
                                    }
                                } else{
                                    prefix = "✅";
                                }
                                $(`.shoplifting-item-detail-name[data-security="${detail['title']}"]`).text(`${prefix} ${detail["title"]}`)
                            }
                        }

                    }

                    if(notification.length > 0){
                        notify(notification);
                        $(".shoplifting_watcher").attr("title", `Shoplifting Watcher\n${notification}`)
                    }
                });
            }
        });
    }

    const insert_body = ()=>{
        const watcher = $(`<div id="shoplifting-body" class="hidden">
            <div class="shoplifting-status">
            </div>
            <div class="shoplifting-apiusage">
                <div>Query interval: </div>
            </div>
        </div>`);
        
        const input = $(`<input type="number" class="shoplifting-interval-input" step="1" value="${watcher_config.interval}"/>`);
        input.keyup(function(){
            const new_val = parseInt($(this).val());
            if(new_val !== watcher_config.interval){
                watcher_config.interval = new_val;
                if(watcher_interval){
                    clearInterval(watcher_interval);
                    watcher_interval = setInterval(()=>{
                        update_watcher();
                    }, watcher_config.interval*1000)
                }
                update_config();
            }
        })

        watcher.find(".shoplifting-apiusage").append(input);

        let title_content = "Shoplifting watcher";
        if(!API){
            title_content = "No Public API"
        }
        const title = $(`
            <div class="shoplifting-title" title="Click to close">
                <div class="heading">${title_content}</div>
                <div class='close-btn'>❌</div>
            </div>`
        );

        title.click(function(){
            $("div#shoplifting-body").addClass("hidden");
        });

        watcher.prepend(title);
        $(body).append(watcher);

        update_watcher();
        if(!watcher_interval){
            watcher_interval = setInterval(()=>{
                update_watcher();
            }, watcher_config.interval*1000);
        }

        insert_icon();

    }

    insert_body();

})();