Branded Torn Wars revive request button with save price checkbox
目前為
// ==UserScript==
// @name Torn Wars Revive Request Button
// @namespace http://tampermonkey.net/
// @version 1.1
// @description Branded Torn Wars revive request button with save price checkbox
// @match https://www.torn.com/*
// @grant GM_xmlhttpRequest
// @grant GM_getValue
// @grant GM_setValue
// @license MIT
// ==/UserScript==
(function() {
'use strict';
const SCRIPT_VERSION = "1.1";
// Create button
const btn = document.createElement('button');
btn.textContent = "TW Revive ⚡";
// Styling: smaller, blue, branded
btn.style.position = "fixed";
btn.style.top = "25%";
btn.style.right = "30px";
btn.style.transform = "translateY(-50%)";
btn.style.padding = "10px 12px";
btn.style.fontSize = "12px";
btn.style.fontWeight = "600";
btn.style.color = "#fff";
btn.style.backgroundColor = "#3498db";
btn.style.border = "2px solid #2980b9";
btn.style.borderRadius = "6px";
btn.style.boxShadow = "0 0 10px rgba(0,0,0,0.3)";
btn.style.cursor = "pointer";
btn.style.zIndex = "99999";
btn.style.fontFamily = "Arial, sans-serif";
btn.onmouseover = () => btn.style.backgroundColor = "#2980b9";
btn.onmouseout = () => btn.style.backgroundColor = "#3498db";
document.body.appendChild(btn);
btn.addEventListener('click', () => {
let apiKey = GM_getValue("torn_api_key", null);
let savedPrice = GM_getValue("revive_price", null);
if (!apiKey) {
apiKey = prompt("Please enter your Torn PUBLIC API key:");
if (!apiKey) {
alert("No API key set. Cannot send revive request.");
return;
}
GM_setValue("torn_api_key", apiKey);
alert("API key saved! Future requests will use this key automatically.");
}
// Always show modal, pre-fill if savedPrice exists
showPriceModal(apiKey, savedPrice);
});
function showPriceModal(apiKey, savedPrice) {
const overlay = document.createElement('div');
overlay.style.position = "fixed";
overlay.style.top = "0";
overlay.style.left = "0";
overlay.style.width = "100%";
overlay.style.height = "100%";
overlay.style.backgroundColor = "rgba(0,0,0,0.5)";
overlay.style.zIndex = "100000";
const modal = document.createElement('div');
modal.style.position = "fixed";
modal.style.top = "50%";
modal.style.left = "50%";
modal.style.transform = "translate(-50%, -50%)";
modal.style.backgroundColor = "#fff";
modal.style.padding = "20px";
modal.style.borderRadius = "8px";
modal.style.boxShadow = "0 0 15px rgba(0,0,0,0.5)";
modal.style.width = "300px";
modal.style.textAlign = "left";
// Payment type
const typeLabel = document.createElement('label');
typeLabel.textContent = "Payment Type:";
typeLabel.style.display = "block";
typeLabel.style.marginBottom = "6px";
typeLabel.style.fontWeight = "600";
const typeSelect = document.createElement('select');
typeSelect.style.width = "100%";
typeSelect.style.marginBottom = "12px";
["Cash", "Xanax"].forEach(opt => {
const o = document.createElement('option');
o.value = opt;
o.textContent = opt;
typeSelect.appendChild(o);
});
// Price options
const priceLabel = document.createElement('label');
priceLabel.textContent = "Revive Price:";
priceLabel.style.display = "block";
priceLabel.style.marginBottom = "6px";
priceLabel.style.fontWeight = "600";
const priceSelect = document.createElement('select');
priceSelect.style.width = "100%";
priceSelect.style.marginBottom = "12px";
function updatePriceOptions() {
priceSelect.innerHTML = "";
let options = typeSelect.value === "Cash"
? ["1m", "2m", "5m"]
: ["1 Xanax", "2 Xanax", "5 Xanax"];
options.forEach(opt => {
const o = document.createElement('option');
o.value = opt;
o.textContent = opt;
priceSelect.appendChild(o);
});
if (savedPrice) {
priceSelect.value = savedPrice;
}
}
typeSelect.onchange = updatePriceOptions;
updatePriceOptions();
// Revive skill
const skillLabel = document.createElement('label');
skillLabel.textContent = "Required Revive Skill:";
skillLabel.style.display = "block";
skillLabel.style.marginBottom = "6px";
skillLabel.style.fontWeight = "600";
const skillSelect = document.createElement('select');
skillSelect.style.width = "100%";
skillSelect.style.marginBottom = "12px";
["At least 25%", "At least 50%", "At least 75%", "Full (100%)"].forEach(opt => {
const o = document.createElement('option');
o.value = opt;
o.textContent = opt;
skillSelect.appendChild(o);
});
// Checkbox
const checkboxLabel = document.createElement('label');
checkboxLabel.style.display = "flex";
checkboxLabel.style.alignItems = "center";
checkboxLabel.style.marginBottom = "12px";
const checkbox = document.createElement('input');
checkbox.type = "checkbox";
checkbox.style.marginRight = "6px";
checkboxLabel.appendChild(checkbox);
checkboxLabel.appendChild(document.createTextNode("Save this price"));
// Buttons
const buttonContainer = document.createElement('div');
buttonContainer.style.textAlign = "center";
buttonContainer.style.marginTop = "8px";
const sendBtn = document.createElement('button');
sendBtn.textContent = "Send";
sendBtn.style.margin = "4px";
sendBtn.style.padding = "4px 8px";
sendBtn.style.backgroundColor = "#3498db";
sendBtn.style.color = "#fff";
sendBtn.style.border = "none";
sendBtn.style.borderRadius = "4px";
sendBtn.style.cursor = "pointer";
sendBtn.style.fontSize = "12px";
const cancelBtn = document.createElement('button');
cancelBtn.textContent = "Cancel";
cancelBtn.style.margin = "4px";
cancelBtn.style.padding = "4px 8px";
cancelBtn.style.backgroundColor = "#aaa";
cancelBtn.style.color = "#fff";
cancelBtn.style.border = "none";
cancelBtn.style.borderRadius = "4px";
cancelBtn.style.cursor = "pointer";
cancelBtn.style.fontSize = "12px";
buttonContainer.appendChild(sendBtn);
buttonContainer.appendChild(cancelBtn);
modal.appendChild(typeLabel);
modal.appendChild(typeSelect);
modal.appendChild(priceLabel);
modal.appendChild(priceSelect);
modal.appendChild(skillLabel);
modal.appendChild(skillSelect);
modal.appendChild(checkboxLabel);
modal.appendChild(buttonContainer);
overlay.appendChild(modal);
document.body.appendChild(overlay);
sendBtn.onclick = () => {
const price = priceSelect.value;
const skill = skillSelect.value;
const type = typeSelect.value;
if (!price) return;
if (checkbox.checked) {
GM_setValue("revive_price", price);
}
sendToController({ type, price, skill }, apiKey);
document.body.removeChild(overlay);
};
cancelBtn.onclick = () => {
document.body.removeChild(overlay);
};
}
function sendToController(data, apiKey) {
GM_xmlhttpRequest({
method: "POST",
url: "https://tornwars.com/api/dashboard/revive/script",
headers: { "Content-Type": "application/json" },
data: JSON.stringify({
apiKey: apiKey,
...data,
scriptVersion: SCRIPT_VERSION
}),
onload: function(response) {
console.log("Sent to controller:", response);
}
});
}
})();