您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Commonly used functions in my Torn scripts.
当前为
此脚本不应直接安装。它是供其他脚本使用的外部库,要使用该库请加入元指令 // @require https://update.greasyfork.icu/scripts/392610/750739/DKK%20Torn%20Utilities%20DEVELOPMENT.js
// ==UserScript== // @name DKK Torn Utilities DEVELOPMENT // @description Commonly used functions in my Torn scripts. // @version 1.8.7 // @exclude * // @namespace https://openuserjs.org/users/DeKleineKobini // @homepageURL https://www.torn.com/forums.php#/p=threads&t=16110079 // ==/UserScript== /* Script Setup */ addFunctions(); function addFunctions() { // formating for numbers Number.prototype.format = function(n, x) { var re = '\\d(?=(\\d{' + (x || 3) + '})+' + (n > 0 ? '\\.' : '$') + ')'; return this.toFixed(Math.max(0, ~~n)).replace(new RegExp(re, 'g'), '$&,'); }; } function initScript(options) { // some easy name conversion if (options.name) { if (!options.id) options.id = replaceAll(options.name, " ", "").toLowerCase(); if (!options.abbr) options.abbr = ""; } if (!options.logging) { options.logging = "ERROR"; } // actually init if (options.api){ if (options.apikey) _setAPI(options.apikey); requireAPI(); } if (!unsafeWindow.scripts) unsafeWindow.scripts = { ids: [] }; unsafeWindow.scripts.ids.push(options.id); unsafeWindow.scripts[options.id] = { name: options.name, abbr: options.short, api: options.api ? true : false }; dkklog.level = dkklog.levels[options.logging]; dkklog.prefix = "[" + options.abbr + "]"; } /* Messaging */ var dkklog = { prefix: "[DKK]", level: 2, // show warnings by default levels: { FATAL: 0, ERROR: 1, WARN: 2, INFO: 3, DEBUG: 4, TRACE: 5, ALL: 6, OFF: 7 }, logging: function (level, message, objs) { if (dkklog.loggingLevel < dkklog.levels[level]) return; let msg = `${dkklog.prefix}[${Object.getOwnPropertyNames(dkklog.levels)[dkklog.level]}] ${message}`; if (objs.length) console.log(msg, ...objs); else console.log(msg) }, fatal: function (message) { dkklog.logging("FATAL", message); }, error: function (message, ...objs) { dkklog.logging("ERROR", message); }, warn: function (message, ...objs) { dkklog.logging("WARN", message); }, info: function (message, ...objs) { dkklog.logging("INFO", message); }, debug: function (message, ...objs) { dkklog.logging("DEBUG", message, objs); }, trace: function (message, ...objs) { dkklog.logging("TRACE", message); }, all: function (message, ...objs) { dkklog.logging("ALL", message); } } /* Torn API */ var apiKey; const API_LENGTH = 16; const STORAGE_LOCATION = "dkkutils_apikey"; function requireAPI() { dkklog.debug("Require API") apiKey = getAPI(); if (!_isValidAPIKey(apiKey)) { dkklog.debug("Require API - no valid api found") let response = prompt("Please enter your API key: "); if (_isValidAPIKey(response)) { setAPI(response); } else { dkklog.debug("Require API - no valid api given") alert("Given API key was not valid, script might not work.\nRefresh to try again.") } } } function _isValidAPIKey(key) { if (!key) key = apiKey; if (!key || key === undefined || key == "undefined" || key === null || key == "null" || key === "") return false; if (key.length != API_LENGTH) return false; return true; } function sendAPIRequest(part, id, selections, key) { dkklog.debug(`Sending API request to ${part}/${selections} on id ${id}`); if (!key) key = apiKey; return new Promise((resolve, reject) => { GM_xmlhttpRequest({ method: "GET", url: `https://api.torn.com/${part}/${id}?selections=${selections}&key=${key}`, onreadystatechange: function(res) { if (res.readyState > 3 && res.status === 200) { dkklog.debug("API response received.") if (!isJsonString(res.responseText)) { reject("JSON Error", res.responseText); return; } var json = JSON.parse(res.responseText); resolve(json); if (json.error) { var code = json.error.code; dkklog.debug("API Error: " + code) if (code == 2) setAPI(null); } } }, onerror: function(err) { console.log(err); reject('XHR error.'); } }) }).catch(e => { console.log(e); }); } function setAPI(key) { if (!_isValidAPIKey(key)) { localStorage.removeItem(STORAGE_LOCATION); dkklog.debug("Removed key from storage.") } else { localStorage.setItem(STORAGE_LOCATION, key); dkklog.debug(`Added key '${key}' to storage. '${localStorage.getItem(STORAGE_LOCATION)}'`) } apiKey = key; } function _setAPI(key) { if (!_isValidAPIKey(key)) localStorage.removeItem(STORAGE_LOCATION); else localStorage.setItem(STORAGE_LOCATION, key); apiKey = key; } function getAPI() { let utilsKey = localStorage.getItem(STORAGE_LOCATION); if (_isValidAPIKey(utilsKey)) { dkklog.debug("getAPI - from own storage '" + utilsKey.length + "'"); return utilsKey; } else { dkklog.debug("getAPI - from own storage is invalid '" + utilsKey + "'"); } let key = localStorage.getItem("_apiKey") || localStorage.getItem("x_apikey") || localStorage.getItem("jebster.torn") || localStorage.getItem("TornApiKey"); if (_isValidAPIKey(key)) { dkklog.debug("getAPI - from other storage"); setAPI(key); } else if (localStorage.getItem("_apiKey")) { dkklog.debug("getAPI - removed 1"); localStorage.removeItem("_apiKey"); } else if (localStorage.getItem("x_apikey")) { dkklog.debug("getAPI - removed 2"); localStorage.removeItem("x_apikey"); } else if (localStorage.getItem("jebster.torn")) { dkklog.debug("getAPI - removed 3"); localStorage.removeItem("jebster.torn"); } else if (localStorage.getItem("_apiKey")) { dkklog.debug("getAPI - removed 4"); localStorage.removeItem("TornApiKey"); } return utilsKey; } /* Torn General*/ function getScriptUser() { let body = $("body") let contentWrapper = $("#mainContainer > .content-wrapper"); return { isJailed: body.hasClass("jail"), isHospitalized: body.hasClass("hospital"), isTravelling: contentWrapper.hasClass("travelling") } } /* Networking */ function xhrIntercept(callback) { let oldXHROpen = window.XMLHttpRequest.prototype.open; window.XMLHttpRequest.prototype.open = function() { this.addEventListener('readystatechange', function() { if (this.readyState > 3 && this.status == 200) { var page = this.responseURL.substring(this.responseURL.indexOf("torn.com/") + "torn.com/".length, this.responseURL.indexOf(".php")); var json, uri; if (isJsonString(this.response)) json = JSON.parse(this.response); else uri = getUrlParams(this.responseURL); callback(page, json, uri, this); } }); return oldXHROpen.apply(this, arguments); } } function ajax(callback) { $(document).ajaxComplete((event, xhr, settings) => { if (xhr.readyState > 3 && xhr.status == 200) { if (settings.url.indexOf("torn.com/") < 0) settings.url = "torn.com" + (settings.url.startsWith("/") ? "" : "/") + settings.url; var page = settings.url.substring(settings.url.indexOf("torn.com/") + "torn.com/".length, settings.url.indexOf(".php")); var json, uri; if (isJsonString(xhr.responseText)) json = JSON.parse(xhr.responseText); else uri = getUrlParams(settings.url); callback(page, json, uri, xhr, settings); } }); } function interceptFetch(url, callback) { unsafeWindow.fetch = async (input, options) => { const response = await fetch(input, options) if (response.url.startsWith("https://www.torn.com/" + url)) { let res = response.clone(); Promise.resolve(res.json().then((json) => callback(json, res.url))); } return response; } } /* DOM */ function observeMutationsFull(root, callback, options) { if (!options) options = { childList: true }; new MutationObserver(callback).observe(root, options); } function observeMutations(root, selector, runOnce, callback, options, callbackRemoval) { var ran = false; observeMutationsFull(root, function(mutations, me) { var check = $(selector); if (check.length) { if (runOnce) me.disconnect(); ran = true; callback(mutations, me); } else if (ran) { ran = false; if (callbackRemoval) callbackRemoval(mutations, me); } }, options); } /* Caching */ function setCache(key, value, time, sub) { var end = time == -1 ? -1 : Date.now() + time; var obj = sub ? value : { value: value, end: Date.now() + time }; GM_setValue(key, JSON.stringify(obj)); } async function getCache(key, subbed) { let _obj = await GM_getValue(key, subbed ? "{}" : "{\"end\":0}"); let obj = JSON.parse(_obj); var end = obj.end; if (!end || end == -1 || end > Date.now()) return subbed ? obj : obj.value; return undefined; } function getSubCache(cache, id) { if (cache[id]) { var end = cache[id].end; if (end == -1 || end > Date.now()) return cache[id].value; } return undefined; } /* General Utilities */ function isJsonString(str) { if (!str || str == "") return false; try { JSON.parse(str); } catch (e) { return false; } return true; } /** * JavaScript Get URL Parameter (https://www.kevinleary.net/javascript-get-url-parameters/) * * @param String prop The specific URL parameter you want to retreive the value for * @return String|Object If prop is provided a string value is returned, otherwise an object of all properties is returned */ function getUrlParams(url, prop) { var params = {}; var search = decodeURIComponent(((url) ? url : window.location.href).slice(window.location.href.indexOf('?') + 1)); var definitions = search.split('&'); definitions.forEach(function(val, key) { var parts = val.split('=', 2); params[parts[0]] = parts[1]; }); return (prop && prop in params) ? params[prop] : params; } function getSpecialSearch() { let hash = window.location.hash; hash = hash.replace("#/", "?"); hash = hash.replace("#!", "?"); return hash; } function replaceAll(str, text, replace) { while (contains(str, text)) { str = str.replace(text, replace); } return str; } function contains(str, text) { return str.indexOf(text) >= 0; } function stripHtml(html) { var tmp = document.createElement("DIV"); tmp.innerHTML = html; var stripped = tmp.textContent || tmp.innerText || ""; stripped = replaceAll(stripped, "\n", ""); stripped = replaceAll(stripped, "\t", ""); stripped = replaceAll(stripped, " ", " "); return stripped; } function getNewDay() { let now = new Date(); let newDay = new Date(Date.UTC(now.getFullYear(), now.getMonth(), now.getDate() - 1, 0, 0, 0)); if (Date.now() >= newDay.getTime()) newDay.setUTCDate(newDay.getUTCDate() + 1); if (Date.now() >= newDay.getTime()) newDay.setUTCDate(newDay.getUTCDate() + 1); return newDay; } function getMillisUntilNewDay() { return getNewDay().getTime() - Date.now(); } function _isMobile() { return navigator.userAgent.match(/Android/i) || navigator.userAgent.match(/webOS/i) || navigator.userAgent.match(/iPhone/i) || navigator.userAgent.match(/iPad/i) || navigator.userAgent.match(/iPod/i) || navigator.userAgent.match(/BlackBerry/i) || navigator.userAgent.match(/Windows Phone/i); } function runOnEvent(funct, event, runBefore) { if (runBefore) funct(); $(window).bind(event, function() { funct(); }); } function timeSince(timeStamp) { let now = new Date(); let secondsPast = (now.getTime() - timeStamp.getTime()) / 1000; if (secondsPast < 60) return parseInt(secondsPast) + 's'; else if (secondsPast < 3600) return parseInt(secondsPast / 60) + 'm'; else if (secondsPast <= 86400) return parseInt(secondsPast / 3600) + 'h'; else if (secondsPast > 86400) { let day = timeStamp.getDate(); let month = timeStamp.toDateString().match(/ [a-zA-Z]*/)[0].replace(" ", ""); let year = timeStamp.getFullYear() == now.getFullYear() ? "" : " " + timeStamp.getFullYear(); return day + " " + month + year; } }