shoplifting-watcher

Watch shoplifting status for players.

Du musst eine Erweiterung wie Tampermonkey, Greasemonkey oder Violentmonkey installieren, um dieses Skript zu installieren.

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

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

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

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

Sie müssten eine Skript Manager Erweiterung installieren damit sie dieses Skript installieren können

(Ich habe schon ein Skript Manager, Lass mich es installieren!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(I already have a user style manager, let me install it!)

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

(function(){
    'use strict';
    
    // Avoid duplicated loading
    if(window.SHOPLIFTING_WATCHER){
        return;
    }
    window.SHOPLIFTING_WATCHER = true;

    // ============================= Configuration ==============================
    let API = localStorage.getItem("APIKey") || "";
    const CONFIG_STORAGE_KEY = "SHOPLIFTING_WATCHER"
    let watcher_config = {
        interval: 60, // second,
        enabled: [],
        collapsed: false,
        disabled: false,
        offset: [30, 30],
        both: [],
        sort: [],
    }
    // ==========================================================================
    let inPDA = false;
    const PDAKey = "###PDA-APIKEY###";
    if(PDAKey.charAt(0) !== "#"){
        inPDA = true;
        if(!API){
            API = PDAKey;
        }
    }
    if(localStorage.getItem(CONFIG_STORAGE_KEY)){
        const config = JSON.parse(localStorage.getItem(CONFIG_STORAGE_KEY));
        if(config["collapsed"] === undefined || config["sort"] === undefined || config["both"] === undefined){
            update_config();
        } else{
            watcher_config = config;
        }
    }

    if(API && !localStorage.getItem("APIKey")){
        localStorage.setItem("APIKey", API);
    }

    // Ensure single instance, thanks to Silmaril :D
    const scriptIsRunningKey = 'nodelore.torn.shoplifting-watcher.is-running';
    const lastQueriedKey = "nodelore.torn.shoplifting-watcher.last-queried";

    const currentTimestamp = parseInt(new Date().getTime() / 1000);
    if(!localStorage.getItem(lastQueriedKey) || (currentTimestamp - parseInt(localStorage.getItem(lastQueriedKey)) > 5 * watcher_config.interval)){
        console.log("[ShopliftingWatcher] Reset running flag to false");
        localStorage.removeItem(scriptIsRunningKey);
    }

    if (localStorage.getItem(scriptIsRunningKey) === 'true') {
        console.log("[ShopliftingWatcher] Script is already running in another tab.");
        return;
    }

    console.log("[ShopliftingWatcher] Script started working.");
    localStorage.setItem(scriptIsRunningKey, 'true');

    window.addEventListener('beforeunload', () => {
        localStorage.removeItem(scriptIsRunningKey);
    });

    window.addEventListener('unload', () => {
        localStorage.removeItem(scriptIsRunningKey);
    });

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

    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 addStyle = ()=>{
        const styles = `
            .dark-mode #shoplifting-body *{
                color: #000;
            }
            
            .dragging{
                opacity: .5;
            }

            .collapsed .shoplifting-status{
                overflow: hidden;
                height: auto;
            }

            .collapsed .shoplifting-item:not(.active){
                display: none;
            }

            .collapsed .shoplifting-item-detail:not(.active){
                display: none;
            }

            #shoplifting-body{
                display: flex;
                position: fixed;
                width: 300px;
                height: auto;
                background: #FFF;
                border-radius: 6px;
                box-sizing: border-box;
                padding: 10px 10px 0 10px;
                flex-flow: column nowrap;
                z-index: 1000000;
            }

            #shoplifting-body *{
                user-select: none;
            }

            #shoplifting-body.hidden{
                display: none !important;
            }

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

            .shoplifting-title div.heading{
                font-size: 15px;
                font-weight: bold;
                cursor: grab;
            }

            .shoplifting-title div.close-btn{
                margin-left: auto;
                cursor: pointer !important;;
            }

            .shoplifting-status{
                width: 100%;
                display: flex;
                height: 300px;
                flex-flow: column nowrap;
                overflow-y: scroll;
                padding-right: 15px;
            }

            .shoplifting-status::-webkit-scrollbar{
                width: 10px;
            }

            .shoplifting-status::-webkit-scrollbar-thumb {
                border-radius: 10px;
                box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.2);
                background: #a8bbbf;
                background-image: -webkit-linear-gradient(
                    45deg,
                    rgba(255, 255, 255, 0.2) 25%,
                    transparent 25%,
                    transparent 50%,
                    rgba(255, 255, 255, 0.2) 50%,
                    rgba(255, 255, 255, 0.2) 75%,
                    transparent 75%,
                    transparent
                );
            }

            .shoplifting-status:-webkit-scrollbar-track {
                box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.2);
                border-radius: 10px;
                background-color: #ededed;
            }

            .shoplifting-item{
                width: 100%;
                display: flex;
                flex-flow: column nowrap;
                border-top: 1px solid rgba(1, 1, 1, .1);
                box-sizing: border-box;
                padding: 5px 0;
                position: relative;
            }

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

            .shoplifting-item-name{
                font-weight: bold;
                height: 20px;
                line-height: 20px;
                display: flex;
                align-items: center;     
            }

            .shoplifting-item-name span{
                position: relative;
                font-size: 14px;
                cursor: pointer;
                text-indent: 24px;
                transition: .3s all ease-in-out;   
            }

            .shoplifting-item-name span:hover::after{
                opacity: 1;
            }
            
            .stick-top .shoplifting-item-name span::after{
                opacity: 1 !important;
            }

            .shoplifting-item-name span::after{
                opacity: 0;
                content: "\u21EE"; 
                position: absolute;
                left: -21px;
                top: 50%;
                transform: translateY(-50%);
                font-size: 20px; 
                transition: .3s all ease-in-out;  
            }

            .shoplifting-item-detail{
                display: flex;
                align-items: center;
                margin-top: 3px;
            }

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

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

            .shoplifting-item-toggle div{
                width: 60px;
                height: 20px;
                line-height: 20px;
                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: 5px 0 5px 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;
            }

            .toggle-btn{
                position: absolute;
                right: 30px;
            }

            .shoplifting-status .toggle-btn{
                left: 150px;
            }

            .toggle-watcher{
                display: none;
            }

            .toggle-watcher:checked + label{
                background: #82c91e; 
            }

            .toggle-watcher:checked + label:after{
                left: calc(100% - 15px);
            }

            .toggle-watcher + label{
                display: inline-block;
                width: 40px;
                height: 15px;
                position: relative;
                transition: 0.15s;
                margin: 0px 20px;
                box-sizing: border-box;
                background: #ddd;
                border-radius: 20px;
                box-shadow: 1px 1px 3px #aaa;
            }

            .shoplifting-status .toggle-watcher + label:hover::before{
                opacity: 1;
            }

            .toggle-watcher + label:after{
                content: '';
                display: block;
                position: absolute;
                left: 0px;
                top: 0px;
                width: 15px;
                height: 15px;
                transition: 0.15s;
                cursor: pointer;
                background: #fff;
                border-radius: 50%;
                box-shadow: 1px 1px 3px #aaa;
            }

            .shoplifting-status .toggle-watcher + label:before{
                content: 'BOTH';
                position: absolute;
                right: -45px;
                line-height: 21px;
                height: 21px;
                font-size: 12px;
                color: #333;
                transition: .3s all ease-in-out;
                opacity: 0;
            }

            .shoplifting-collapsed{
                padding: 5px 0 5px 0;
                background: #F2F2F2;
                text-align: center;
                border-top: 1px solid rgba(1, 1, 1, .1);
                font-weight: bold;
                transition: .15s all ease-in-out;
                margin-bottom: 8px;
            }

            .shoplifting-collapsed:hover{
                background: #FFF;
                cursor: pointer;
            }

            .both-active{
                cursor: not-allowed !important;
            }

            .both-active div{
                background: #ddd;
                transition: none;
                box-shadow: none;
                color: #333;
                opacity: 1;
            }

            .both-active div:hover{
                opacity: 1;
            }
        `;
        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 is_active = (status)=>{
        for(let item of status){
            if(item === 0){
                return false;
            }
        }
        return true;
    }

    const mock_status = (shop_status, single=true)=>{
        for(let detail of shop_status){
            detail["disabled"] = true;
            if(single){
                break;
            }
        }
    }

    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"];

                    localStorage.setItem(lastQueriedKey, parseInt(new Date().getTime() / 1000))

                    for(let shop_name in shoplifting_data){
                        const shop_status = shoplifting_data[shop_name];
                        const status_record = [];
                        if(!update_flag){
                            const shoplifting_item = $(`
                                <div class="shoplifting-item" data-shop="${shop_name}">
                                </div>
                            `);

                            const shoplifting_name = $(`
                                <div class="shoplifting-item-name">
                                    <span>${shop_name}</span>
                                </div>
                            `);

                            shoplifting_name.find("span").click(function(){
                                const parent = $(this).parent().parent();
                                const shop_name = parent.attr("data-shop");
                                const shop_idx = watcher_config.sort.indexOf(shop_name);
                                if(shop_idx !== -1){
                                    watcher_config.sort.splice(shop_idx, 1);
                                } 
                                watcher_config.sort.unshift(shop_name);
                                if(watcher_config.sort.length > 3){
                                    const pop_item = watcher_config.sort.pop();
                                    const pop = $("#shoplifting-body").find(".shoplifting-status").find(`.shoplifting-item[data-shop=${pop_item}]`);
                                    if(pop.length > 0){
                                        pop.removeClass("stick-top");
                                    }
                                }

                                update_config();
                                if(!parent.hasClass("stick-top")){
                                    parent.addClass("stick-top");
                                }
                                $("#shoplifting-body").find(".shoplifting-status").prepend(parent);
                            });
                            
                            const checked = watcher_config.both.indexOf(shop_name) === -1 ? "" : "checked";
                            const toggle_both = $(`<div class="toggle-btn">
                                <input type="checkbox" class="toggle-watcher" id="${shop_name}-watcher" ${checked}>
                                <label for="${shop_name}-watcher"></label>
                            </div>`);
                    
                            toggle_both.find(`#${shop_name}-watcher`).change(function(){
                                const idx = watcher_config.both.indexOf(shop_name);
                                const parent = $(this).parent().parent().parent().find(".shoplifting-item-toggle");
                                if(idx !== -1){
                                    const idx = watcher_config.both.indexOf(shop_name);
                                    watcher_config.both.splice(idx, 1);
                                    if(parent.hasClass("both-active")){
                                        parent.removeClass("both-active");
                                    }
                                } else{
                                    watcher_config.both.push(shop_name);
                                    if(!parent.hasClass("both-active")){
                                        parent.addClass("both-active");
                                    }
                                }
                                update_config();
                            });
                    
                            shoplifting_name.append(toggle_both);
                    
                            shoplifting_item.append(shoplifting_name);

                            let active_flag = false;

                            for(let detail of shop_status){
                                const detail_item = $(`<div class="shoplifting-item-detail"></div>`)
                                let prefix = ""
                                const key = `${shop_name}_${detail["title"].toLowerCase().replace(" ", "_")}`;
                                if(detail["disabled"]){
                                    prefix = "❌";
                                    status_record.push(1);
                                    if(watcher_config.enabled.indexOf(key) !== -1 && watcher_config.both.indexOf(shop_name) === -1){
                                        if(notification.length > 0){
                                            notification += "\n";
                                        }
                                        notification += `【${shop_name}】【${detail["title"]}】 is disabled`;
                                    }
                                } else{
                                    prefix = "✅";
                                    status_record.push(0);
                                }
                                detail_item.append($(`<div class="shoplifting-item-detail-name" data-key="${key}">${prefix} ${detail["title"]}</div>`));
                                
                                let toggleOn = "";
                                let toggleOff = "";
                                if(watcher_config.enabled.indexOf(key) !== -1){
                                    toggleOn = " active";
                                    detail_item.addClass("active");
                                    active_flag = true;
                                } else{
                                    toggleOff = " active";
                                }
                                const toggle = $(`
                                    <div class="shoplifting-item-toggle" data-key="${key}">
                                        <div class="shoplifting-item-toggle-on${toggleOn}">ON</div>
                                        <div class="shoplifting-item-toggle-off${toggleOff}">OFF</div>
                                    </div>`
                                );

                                if(watcher_config.both.indexOf(shop_name) !== -1){
                                    toggle.addClass("both-active")
                                }
        
                                toggle.click(function(){
                                    const parent = $(this).parent();
                                    const item = parent.parent();
                                    const shop_name = item.attr("data-shop");
                                    const checked = watcher_config.both.indexOf(shop_name) === -1 ? "" : "checked";
                                    if(checked){
                                        return;
                                    }

                                    const key = $(this).attr("data-key");
                                    
                                    if(watcher_config.enabled.indexOf(key) !== -1){
                                        const index = watcher_config.enabled.indexOf(key);
                                        watcher_config.enabled.splice(index, 1);
                                        $(`div.shoplifting-item-toggle[data-key=${key}] .shoplifting-item-toggle-off`).addClass("active");
                                        $(`div.shoplifting-item-toggle[data-key=${key}] .shoplifting-item-toggle-on`).removeClass("active");
                                        parent.removeClass("active");
                                        let clear_flag = true;
                                        item.find(".shoplifting-item-detail").each(function(){
                                            if($(this).hasClass("active")){
                                                clear_flag = false;
                                            }
                                        });
                                        if(clear_flag){
                                            item.removeClass("active");
                                        }
                                    } else{
                                        watcher_config.enabled.push(key);
                                        $(`div.shoplifting-item-toggle[data-key=${key}] .shoplifting-item-toggle-off`).removeClass("active");
                                        $(`div.shoplifting-item-toggle[data-key=${key}] .shoplifting-item-toggle-on`).addClass("active");
                                        
                                        if(!parent.hasClass("active")){
                                            parent.addClass("active");
                                        }
                                        if(!item.hasClass("active")){
                                            item.addClass("active");
                                        }
                                    }
                                    update_config();
                                });
                                detail_item.append(toggle);
                                
                                shoplifting_item.append(detail_item)
                            }
                            
                            if(active_flag){
                                shoplifting_item.addClass("active");
                            }

                            if(watcher_config.sort.length === 0){
                                $("#shoplifting-body").find(".shoplifting-status").append(shoplifting_item);
                            } else{
                                let prev_item;
                                let found = false;
                                for(let i = 0; i < watcher_config.sort.length; i++){
                                    if(watcher_config.sort[i] === shop_name){
                                        const shop_idx = i - 1;
                                        if(shop_idx >= 0){
                                            prev_item = watcher_config.sort[shop_idx];
                                        }
                                        found = true;
                                        break;
                                    }
                                }

                                if(!found){
                                    $("#shoplifting-body").find(".shoplifting-status").append(shoplifting_item);
                                } else{
                                    shoplifting_item.addClass("stick-top");
                                    if(prev_item && $("#shoplifting-body").find(".shoplifting-status").find(`.shoplifting-item[data-shop=${prev_item}]`).length > 0){
                                        $("#shoplifting-body").find(".shoplifting-status").find(`.shoplifting-item[data-shop=${prev_item}]`).after(shoplifting_item)
                                    } else{
                                        $("#shoplifting-body").find(".shoplifting-status").prepend(shoplifting_item);
                                    }
                                }
                            }

                        }
                        else{
                            for(let detail of shop_status){
                                let prefix = "";
                                const key = `${shop_name}_${detail["title"].toLowerCase().replace(" ", "_")}`;
                                if(detail["disabled"]){
                                    prefix = "❌";
                                    status_record.push(1);
                                    if(watcher_config.enabled.indexOf(key) !== -1 && watcher_config.both.indexOf(shop_name) === -1){
                                        if(notification.length > 0){
                                            notification += "\n";
                                        }
                                        notification += `【${shop_name}】【${detail["title"]}】 is disabled`;
                                    }
                                } else{
                                    prefix = "✅";
                                    status_record.push(0);
                                }

                                const target = $(`.shoplifting-item-detail-name[data-key="${key}"]`);
                                target.text(`${prefix} ${detail["title"]}`);
                            }
                        }
                        if(watcher_config.both.indexOf(shop_name) !== -1 && is_active(status_record)){
                            // forbidden notification if any of both is not disabled
                            if(notification.length > 0){
                                notification += "\n";
                            }
                            notification += `【${shop_name}】 ALL securities disabled`;
                        }
                    }
                    if(notification.length > 0){
                        notify(notification);
                        $(".shoplifting_watcher").attr("title", `Shoplifting Watcher\n${notification}`)
                    }
                });
            }
        });
    }

    let is_dragging = false;
    let offset = watcher_config.offset;
    const insert_body = ()=>{
        const collapsed_class = watcher_config.collapsed ? " collapsed" : "";

        const watcher = $(`<div id="shoplifting-body" class="hidden${collapsed_class}">
            <div class="shoplifting-status">
            </div>
            <div class="shoplifting-apiusage">
                <div>Query interval: </div>
            </div>
        </div>`);

        watcher.offset({
            left: offset[0],
            top: offset[1],
        });
        
        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">
                
            </div>`
        );

        const heading = $(`<div class="heading">${title_content}</div>`);
        heading.mousedown(function(e){
            $("#shoplifting-body").addClass("dragging");
            is_dragging = true;
            offset = [
                $("#shoplifting-body").offset().left - e.pageX,
                $("#shoplifting-body").offset().top - e.pageY
            ]
        });

        heading.mousemove(function(e){
            if(is_dragging){
                $("#shoplifting-body").offset({
                    left: e.pageX + offset[0],
                    top: e.pageY + offset[1]
                })
            }
        })

        heading.mouseup(function(){
            $("#shoplifting-body").removeClass("dragging");
            is_dragging = false;
            watcher_config.offset = [$("#shoplifting-body").offset().left, $("#shoplifting-body").offset().top];
            update_config();
        });

        watcher.mouseleave(function(){
            $("#shoplifting-body").removeClass("dragging");
            is_dragging = false;
            watcher_config.offset = [$("#shoplifting-body").offset().left, $("#shoplifting-body").offset().top];
            update_config();
        })

        title.append(heading);

        const checked = watcher_config.disabled ? "" : "checked";

        const disabled_btn = $(`<div class="toggle-btn">
            <input type="checkbox" class="toggle-watcher" id="toggle-watcher" ${checked}>
            <label for="toggle-watcher"></label>
        </div>`);

        disabled_btn.find("#toggle-watcher").change(function(){
            const status = this.checked;
            if(status === true){
                update_watcher();
                if(!watcher_interval){
                    watcher_interval = setInterval(()=>{
                        update_watcher();
                    }, watcher_config.interval*1000);
                    if($("#shoplifting-body").hasClass("collapsed") && !watcher_config.collapsed){
                        $("#shoplifting-body").removeClass("collapsed");
                    }
                }
            } else{
                if(watcher_interval){
                    clearInterval(watcher_interval);
                    watcher_interval = null;
                    $("div.shoplifting-item").each(function(){
                        $(this).remove();
                    });
                    if(!$("#shoplifting-body").hasClass("collapsed")){
                        $("#shoplifting-body").addClass("collapsed");
                    }
                }
            }
            watcher_config.disabled = !status;
            update_config();
        });

        title.append(disabled_btn);

        const close_btn = $(`<div class='close-btn' title="Click to close">❌</div>`);

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

        title.append(close_btn);
        watcher.prepend(title);

        const collapsed = $(`<div class="shoplifting-collapsed">${watcher_config.collapsed ? "Expand" : "Collapsed"}</div>`);
        collapsed.click(function(){
            if(watcher_config.collapsed === true){
                watcher_config.collapsed = false;
                $(this).text("Collapsed");
                if($("#shoplifting-body").hasClass("collapsed")){
                    $("#shoplifting-body").removeClass("collapsed");
                }
            } else{
                watcher_config.collapsed = true;
                $(this).text("Expand");
                if(!$("#shoplifting-body").hasClass("collapsed")){
                    $("#shoplifting-body").addClass("collapsed");
                }
            }
            update_config();
        })

        watcher.append(collapsed);

        $(body).append(watcher);

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

        insert_icon();

    }

    insert_body();

})();