您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
On "Fill" click autofills bazaar item price with lowest bazaar price currently minus $1, shows current price coefficient compared to 3rd lowest, fills max quantity for items, marks checkboxes for guns.
当前为
- // ==UserScript==
- // @name Torn Bazaar Filler
- // @namespace https://github.com/SOLiNARY
- // @version 0.5
- // @description On "Fill" click autofills bazaar item price with lowest bazaar price currently minus $1, shows current price coefficient compared to 3rd lowest, fills max quantity for items, marks checkboxes for guns.
- // @author Ramin Quluzade, Silmaril [2665762]
- // @license MIT License
- // @match https://www.torn.com/bazaar.php
- // @icon https://www.google.com/s2/favicons?sz=64&domain=torn.com
- // @require https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js
- // @run-at document-idle
- // @grant GM_addStyle
- // ==/UserScript==
- (function() {
- 'use strict';
- const bazaarUrl = "https://api.torn.com/market/{itemId}?selections=bazaar&key={apiKey}";
- let apiKey = localStorage.getItem("silmaril-torn-bazaar-filler-apikey");
- // TornPDA support for GM_addStyle
- let GM_addStyle = function (s) {
- let style = document.createElement("style");
- style.type = "text/css";
- style.innerHTML = s;
- document.head.appendChild(style);
- };
- GM_addStyle(`
- .btn-wrap.torn-bazaar-fill-qty-price {
- float: right;
- margin-left: auto;
- }
- div.title-wrap div.name-wrap {
- display: flex;
- justify-content: flex-end;
- }
- .wave-animation {
- position: relative;
- overflow: hidden;
- }
- .wave {
- position: absolute;
- width: 100%;
- height: 33px;
- background-color: transparent;
- opacity: 0;
- transform: translateX(-100%);
- animation: waveAnimation 1s cubic-bezier(0, 0, 0, 1);
- }
- @keyframes waveAnimation {
- 0% {
- opacity: 1;
- transform: translateX(-100%);
- }
- 100% {
- opacity: 0;
- transform: translateX(100%);
- }
- }
- .overlay-percentage {
- position: absolute;
- top: 0px;
- right: -30px;
- background-color: rgba(0, 0, 0, 0.9);
- padding: 0px 5px;
- border-radius: 15px;
- font-size: 10px;
- }
- `);
- var observerTarget = $(".content-wrapper")[0];
- var observerConfig = { attributes: false, childList: true, characterData: false, subtree: true };
- var observer = new MutationObserver(function(mutations) {
- $("ul.ui-tabs-nav").on("click", "li:not(.ui-state-active):not(.ui-state-disabled):not(.m-show)", function() {
- observer.observe(observerTarget, observerConfig);
- });
- $("div.topSection___U7sVi").on("click", "div.linksContainer___LiOTN a[aria-labelledby=add-items]", function(){
- observer.observe(observerTarget, observerConfig);
- });
- $("div.topSection___U7sVi").on("click", "div.listItem___Q3FFU a[aria-labelledby=add-items]", function(){
- observer.observe(observerTarget, observerConfig);
- });
- let containerItems = $("ul.items-cont li.clearfix");
- containerItems.find("div.title-wrap div.name-wrap").each(function(){
- let isParentRowDisabled = this.parentElement.parentElement.classList.contains("disabled");
- let alreadyHasFillBtn = this.querySelector(".btn-wrap.torn-bazaar-fill-qty-price") != null;
- if (!alreadyHasFillBtn && !isParentRowDisabled){
- insertFillAndWaveBtn(this);
- }
- });
- if($("div.amount").length) {
- observer.disconnect();
- }
- });
- observer.observe(observerTarget, observerConfig);
- function insertFillAndWaveBtn(element){
- const waveDiv = document.createElement('div');
- waveDiv.className = 'wave';
- const outerSpan = document.createElement('span');
- outerSpan.className = 'btn-wrap torn-bazaar-fill-qty-price';
- const innerSpan = document.createElement('span');
- innerSpan.className = 'btn';
- const inputElement = document.createElement('input');
- inputElement.type = 'submit';
- inputElement.value = 'Fill';
- inputElement.className = 'torn-btn';
- innerSpan.appendChild(inputElement);
- outerSpan.appendChild(innerSpan);
- element.append(outerSpan, waveDiv);
- $(outerSpan).on("click", "input", function() {
- checkApiKey();
- fillQuantityAndPrice(this);
- event.stopPropagation();
- });
- }
- function insertPercentageSpan(element){
- let moneyGroupDiv = element.parentElement.parentElement.parentElement.parentElement.parentElement
- .querySelector("div.actions-main-wrap div.amount-main-wrap div.price div.input-money-group");
- if (moneyGroupDiv.querySelector("span.overlay-percentage") === null) {
- const percentageSpan = document.createElement('span');
- percentageSpan.className = 'overlay-percentage';
- moneyGroupDiv.appendChild(percentageSpan);
- }
- return moneyGroupDiv.querySelector("span.overlay-percentage");
- }
- function getQuantity(element){
- let rgx = /x(\d+)$/;
- let quantityText = $(element).parent().parent().prev().text();
- let match = rgx.exec(quantityText);
- let quantity = match === null ? 1 : match[1];
- return quantity;
- }
- function fillQuantityAndPrice(element){
- let amountDiv = element.parentElement.parentElement.parentElement.parentElement.parentElement.querySelector("div.amount-main-wrap");
- let priceInputs = amountDiv.querySelectorAll("div.price div input");
- let keyupEvent = new Event("keyup", {bubbles: true});
- let inputEvent = new Event("input", {bubbles: true});
- let image = element.parentElement.parentElement.parentElement.parentElement.querySelector("div.image-wrap img");
- let numberPattern = /\/(\d+)\//;
- let match = image.src.match(numberPattern);
- let extractedItemId = 0;
- if (match) {
- extractedItemId = parseInt(match[1], 10);
- } else {
- console.error("[TornBazaarFiller] ItemId not found!");
- }
- let requestUrl = bazaarUrl
- .replace("{itemId}", extractedItemId)
- .replace("{apiKey}", apiKey);
- let wave = element.parentElement.parentElement.parentElement.parentElement.parentElement.querySelector("div.wave");
- fetch(requestUrl)
- .then(response => response.json())
- .then(data => {
- if (data.error != null && data.error.code === 2){
- apiKey = null;
- localStorage.setItem("silmaril-torn-bazaar-filler-apikey", null);
- wave.style.backgroundColor = "red";
- wave.style.animationDuration = "5s";
- console.error("[TornBazaarFiller] Incorrect Api Key:", data);
- return;
- }
- let lowBallPrice = data.bazaar[0].cost - 1;
- let price3rd = data.bazaar[Math.min(2, data.bazaar.length - 1)].cost;
- let priceCoefficient = ((data.bazaar[0].cost / price3rd) * 100).toFixed(0);
- let percentageOverlaySpan = insertPercentageSpan(element);
- if (priceCoefficient <= 95){
- percentageOverlaySpan.style.display = "block";
- if (priceCoefficient <= 50){
- percentageOverlaySpan.style.color = "red";
- wave.style.backgroundColor = "red";
- wave.style.animationDuration = "5s";
- } else if (priceCoefficient <= 75){
- percentageOverlaySpan.style.color = "yellow";
- wave.style.backgroundColor = "yellow";
- wave.style.animationDuration = "3s";
- } else {
- percentageOverlaySpan.style.color = "green";
- wave.style.backgroundColor = "green";
- }
- percentageOverlaySpan.innerText = priceCoefficient + "%";
- } else {
- percentageOverlaySpan.style.display = "none";
- wave.style.backgroundColor = "green";
- }
- priceInputs[0].value = lowBallPrice;
- priceInputs[1].value = lowBallPrice;
- priceInputs[0].dispatchEvent(inputEvent);
- })
- .catch(error => {
- wave.style.backgroundColor = "red";
- wave.style.animationDuration = "5s";
- console.error("[TornBazaarFiller] Error fetching data:", error);
- });
- wave.style.animation = 'none';
- wave.offsetHeight;
- wave.style.animation = null;
- wave.style.backgroundColor = "transparent";
- wave.style.animationDuration = "1s";
- let isQuantityCheckbox = amountDiv.querySelector("div.amount.choice-container") !== null;
- if (isQuantityCheckbox){
- amountDiv.querySelector("div.amount.choice-container input").click();
- } else {
- let quantityInput = amountDiv.querySelector("div.amount input");
- quantityInput.value = getQuantity(element);
- quantityInput.dispatchEvent(keyupEvent);
- }
- }
- function checkApiKey(){
- if (apiKey === null || apiKey.length != 16){
- let userInput = prompt("Please enter a PUBLIC Api Key, it will be used to get current bazaar prices:");
- if (userInput !== null && userInput.length == 16) {
- apiKey = userInput;
- localStorage.setItem("silmaril-torn-bazaar-filler-apikey", userInput);
- } else {
- console.error("[TornBazaarFiller] User cancelled the Api Key input.");
- }
- }
- }
- })();