您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Add customizable buttons to Torn.com chat
当前为
// ==UserScript== // @name Torn.com Enhanced Chat Buttons V2 // @namespace http://tampermonkey.net/ // @version 1.0 // @description Add customizable buttons to Torn.com chat // @author Created by Callz [2188704], updated by Weav3r [1853324] // @match https://www.torn.com/* // @grant GM_setClipboard // ==/UserScript== (function() { 'use strict'; const buttonCSS = ` .custom-chat-button { background-color: #007BFF; color: white; padding: 2px 7px; text-align: center; text-decoration: none; display: inline-block; font-size: 14px; margin: 4px 6px; cursor: pointer; border-radius: 5px; border: none; transition: background-color 0.3s ease; min-width: 80px; overflow: hidden; white-space: nowrap; } .custom-chat-button:hover { background-color: #0056b3; } .custom-chat-button.recent { border: 2px solid #FFD700; box-shadow: 0 0 5px rgba(255, 215, 0, 0.8); } .custom-ui-panel label { font-size: 20px; margin-bottom: 20px; } .custom-ui-panel { position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); background-color: #f5f5f5; padding: 20px; color: black; border-radius: 10px; box-shadow: 0 0 10px rgba(0, 0, 0, 0.2); z-index: 9999999999; max-width: 70%; } .custom-ui-panel h3 { font-size: 20px; margin-bottom: 20px; } .custom-ui-panel input[type="text"], .custom-ui-panel select, .custom-ui-panel textarea { width: 90%; padding: 10px; margin-top:10px; margin-bottom: 15px; border: 1px solid #ccc; border-radius: 5px; font-size: 16px; } .custom-ui-panel input[type="color"] { padding: 0; } .custom-ui-panel button { background-color: #007BFF; color: white; border: none; padding: 10px 16px; border-radius: 5px; cursor: pointer; margin: 10px 5px; font-size: 16px; transition: background-color 0.3s ease; } .custom-ui-panel button#close-ui { background-color: #ccc; margin-right: 10px; } .custom-ui-panel button#close-ui:hover { background-color: #999; } .custom-ui-panel textarea { height: 100px; resize: vertical; } .custom-ui-panel hr { margin: 20px 0; border: 0; border-top: 1px solid #ccc; } #chat-config-button { color:green; } #button-configs { max-height: 200px; overflow-y: scroll; } `; const conditions = { TradeChat: chatBox => chatBox.querySelector('.chat-box-header__name___jIjjM').textContent === 'Trade', HospitalChat: chatBox => chatBox.querySelector('.chat-box-header__name___jIjjM').textContent === 'Hospital', FactionChat: chatBox => chatBox.querySelector('.chat-box-header__name___jIjjM').textContent === 'Faction', CompanyChat: chatBox => chatBox.querySelector('.chat-box-header__name___jIjjM').textContent === 'Company', GlobalChat: chatBox => chatBox.querySelector('.chat-box-header__name___jIjjM').textContent === 'Global', UserChat: chatBox => chatBox.querySelector('.chat-box-header__options___nTsMU'), }; function addCSS(cssString) { const style = document.createElement('style'); style.textContent = cssString; document.head.append(style); } function getButtonConfigurations() { return JSON.parse(localStorage.getItem('chatButtonConfig')) || { buttons: [] }; } function saveButtonConfigurations(config) { localStorage.setItem('chatButtonConfig', JSON.stringify(config)); } function createUIPanel() { const panel = document.createElement('div'); panel.className = 'custom-ui-panel'; panel.innerHTML = ` <h3>Chat Button Configuration</h3> <div id="button-configs"></div> <hr> <div> <input type="text" id="button-text" placeholder="Button Text"> <label for="button-color">Background Color:</label> <input type="color" id="button-color"> <select id="button-condition"> <option value="TradeChat">Trade Chat</option> <option value="HospitalChat">Hospital Chat</option> <option value="FactionChat">Faction Chat</option> <option value="CompanyChat">Company Chat</option> <option value="GlobalChat">Global Chat</option> <option value="UserChat">User Chat</option> </select> <textarea id="button-text-content" placeholder="Add the text here that should be pasted in chat. You can use {name} to get the name of the active chat"></textarea> <button id="add-button">Add Button</button> <button id="edit-button" style="display: none;">Edit Button</button> </div> <button id="close-ui">Close</button> `; document.body.appendChild(panel); document.getElementById('add-button').addEventListener('click', addNewButtonConfig); document.getElementById('edit-button').addEventListener('click', editButtonConfig); document.getElementById('close-ui').addEventListener('click', closeUI); populateButtonConfigs(); } function populateButtonConfigs() { const configsContainer = document.getElementById('button-configs'); configsContainer.innerHTML = ''; const configs = getButtonConfigurations(); configs.buttons.forEach((buttonConfig, index) => { const configDiv = document.createElement('div'); configDiv.innerHTML = ` <div>Text: ${buttonConfig.buttonText}</div> <div>Color: ${buttonConfig.backgroundColor}</div> <div>Condition: ${buttonConfig.condition}</div> <div>Message: ${buttonConfig.text}</div> `; const editButton = document.createElement('button'); editButton.textContent = 'Edit'; editButton.addEventListener('click', () => selectForEdit(index)); configDiv.appendChild(editButton); const deleteButton = document.createElement('button'); deleteButton.textContent = 'Delete'; deleteButton.addEventListener('click', () => deleteButtonConfig(index)); configDiv.appendChild(deleteButton); configsContainer.appendChild(configDiv); }); } function selectForEdit(index) { const config = getButtonConfigurations().buttons[index]; document.getElementById('button-text').value = config.buttonText; document.getElementById('button-color').value = config.backgroundColor; document.getElementById('button-condition').value = config.condition; document.getElementById('button-text-content').value = config.text; document.getElementById('edit-button').style.display = 'block'; document.getElementById('edit-button').setAttribute('data-edit-index', index); } function deleteButtonConfig(index) { const config = getButtonConfigurations(); config.buttons.splice(index, 1); saveButtonConfigurations(config); populateButtonConfigs(); } function addNewButtonConfig() { const buttonText = document.getElementById('button-text').value; const backgroundColor = document.getElementById('button-color').value; const condition = document.getElementById('button-condition').value; const text = document.getElementById('button-text-content').value; const config = getButtonConfigurations(); config.buttons.push({ buttonText, backgroundColor, condition, text }); saveButtonConfigurations(config); populateButtonConfigs(); } function editButtonConfig() { const index = parseInt(document.getElementById('edit-button').getAttribute('data-edit-index'), 10); const buttonText = document.getElementById('button-text').value; const backgroundColor = document.getElementById('button-color').value; const condition = document.getElementById('button-condition').value; const text = document.getElementById('button-text-content').value; const config = getButtonConfigurations(); config.buttons[index] = { buttonText, backgroundColor, condition, text }; saveButtonConfigurations(config); populateButtonConfigs(); } function closeUI() { document.querySelector('.custom-ui-panel').remove(); } function createConfigButton() { const settingsPanel = document.querySelector('.settings-panel___IZSDs'); if (settingsPanel && !document.querySelector('#chat-config-button')) { const configButton = document.createElement('button'); configButton.id = 'chat-config-button'; configButton.textContent = 'Edit Chat Buttons'; configButton.addEventListener('click', createUIPanel); settingsPanel.appendChild(configButton); } } function applyButtonConfigurations() { const configs = getButtonConfigurations(); document.querySelectorAll('.chat-box___mHm01').forEach(chatBox => { configs.buttons.forEach(buttonConfig => { const conditionFunc = conditions[buttonConfig.condition]; if (conditionFunc && conditionFunc(chatBox) && !chatBox.querySelector(`[data-button-text="${buttonConfig.buttonText}"]`)) { const button = document.createElement('button'); button.className = 'custom-chat-button'; button.innerText = buttonConfig.buttonText; button.style.backgroundColor = buttonConfig.backgroundColor; button.setAttribute('data-button-text', buttonConfig.buttonText); button.addEventListener('click', (event) => addCustomText(chatBox, buttonConfig.text, event)); const filterContainer = chatBox.querySelector('.tt-chat-filter'); filterContainer.insertBefore(button, filterContainer.firstChild); } }); }); } function addCustomText(chatBox, messageTemplate, event) { const nameElement = chatBox.querySelector('.typography___Dc5WV'); const name = nameElement ? nameElement.textContent.trim() : 'Trader'; const message = messageTemplate.replace('{name}', name); navigator.clipboard.writeText(message).then(() => { const textArea = chatBox.querySelector('textarea'); textArea.focus(); const startPos = textArea.selectionStart; const endPos = textArea.selectionEnd; textArea.setRangeText(message, startPos, endPos, 'end'); textArea.dispatchEvent(new Event('input', { bubbles: true })); textArea.focus(); textArea.selectionStart = textArea.selectionEnd = startPos + message.length; chatBox.querySelectorAll('.custom-chat-button').forEach(btn => { btn.classList.remove('recent'); }); event.target.classList.add('recent'); }); } addCSS(buttonCSS); const chatContainerObserver = new MutationObserver(function(mutations) { mutations.forEach(function(mutation) { createConfigButton(); applyButtonConfigurations(); }); }); const chatContainer = document.querySelector('#chatRoot'); if (chatContainer) { chatContainerObserver.observe(chatContainer, { childList: true, subtree: true }); } applyButtonConfigurations(); })();