Watch shoplifting status for players.
当前为
// ==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();
})();