Torn.com Enhanced Chat Buttons V2

Add customizable buttons to Torn.com chat

当前为 2024-05-24 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Torn.com Enhanced Chat Buttons V2
  3. // @namespace http://tampermonkey.net/
  4. // @version 1.0
  5. // @description Add customizable buttons to Torn.com chat
  6. // @author Created by Callz [2188704], updated by Weav3r [1853324]
  7. // @match https://www.torn.com/*
  8. // @grant GM_setClipboard
  9. // ==/UserScript==
  10.  
  11. (function() {
  12. 'use strict';
  13.  
  14. const buttonCSS = `
  15. .custom-chat-button {
  16. background-color: #007BFF;
  17. color: white;
  18. padding: 2px 7px;
  19. text-align: center;
  20. text-decoration: none;
  21. display: inline-block;
  22. font-size: 14px;
  23. margin: 4px 6px;
  24. cursor: pointer;
  25. border-radius: 5px;
  26. border: none;
  27. transition: background-color 0.3s ease;
  28. min-width: 80px;
  29. overflow: hidden;
  30. white-space: nowrap;
  31. }
  32.  
  33. .custom-chat-button:hover {
  34. background-color: #0056b3;
  35. }
  36.  
  37. .custom-chat-button.recent {
  38. border: 2px solid #FFD700;
  39. box-shadow: 0 0 5px rgba(255, 215, 0, 0.8);
  40. }
  41.  
  42. .custom-ui-panel label {
  43. font-size: 20px;
  44. margin-bottom: 20px;
  45. }
  46.  
  47. .custom-ui-panel {
  48. position: fixed;
  49. top: 50%;
  50. left: 50%;
  51. transform: translate(-50%, -50%);
  52. background-color: #f5f5f5;
  53. padding: 20px;
  54. color: black;
  55. border-radius: 10px;
  56. box-shadow: 0 0 10px rgba(0, 0, 0, 0.2);
  57. z-index: 9999999999;
  58. max-width: 70%;
  59. }
  60.  
  61. .custom-ui-panel h3 {
  62. font-size: 20px;
  63. margin-bottom: 20px;
  64. }
  65.  
  66. .custom-ui-panel input[type="text"],
  67. .custom-ui-panel select,
  68. .custom-ui-panel textarea {
  69. width: 90%;
  70. padding: 10px;
  71. margin-top:10px;
  72. margin-bottom: 15px;
  73. border: 1px solid #ccc;
  74. border-radius: 5px;
  75. font-size: 16px;
  76. }
  77.  
  78. .custom-ui-panel input[type="color"] {
  79. padding: 0;
  80. }
  81.  
  82. .custom-ui-panel button {
  83. background-color: #007BFF;
  84. color: white;
  85. border: none;
  86. padding: 10px 16px;
  87. border-radius: 5px;
  88. cursor: pointer;
  89. margin: 10px 5px;
  90. font-size: 16px;
  91. transition: background-color 0.3s ease;
  92. }
  93.  
  94. .custom-ui-panel button#close-ui {
  95. background-color: #ccc;
  96. margin-right: 10px;
  97. }
  98.  
  99. .custom-ui-panel button#close-ui:hover {
  100. background-color: #999;
  101. }
  102.  
  103. .custom-ui-panel textarea {
  104. height: 100px;
  105. resize: vertical;
  106. }
  107. .custom-ui-panel hr {
  108. margin: 20px 0;
  109. border: 0;
  110. border-top: 1px solid #ccc;
  111. }
  112. #chat-config-button {
  113. color:green;
  114. }
  115. #button-configs {
  116. max-height: 200px;
  117. overflow-y: scroll;
  118. }
  119. `;
  120.  
  121. const conditions = {
  122. TradeChat: chatBox => chatBox.querySelector('.chat-box-header__name___jIjjM').textContent === 'Trade',
  123. HospitalChat: chatBox => chatBox.querySelector('.chat-box-header__name___jIjjM').textContent === 'Hospital',
  124. FactionChat: chatBox => chatBox.querySelector('.chat-box-header__name___jIjjM').textContent === 'Faction',
  125. CompanyChat: chatBox => chatBox.querySelector('.chat-box-header__name___jIjjM').textContent === 'Company',
  126. GlobalChat: chatBox => chatBox.querySelector('.chat-box-header__name___jIjjM').textContent === 'Global',
  127. UserChat: chatBox => chatBox.querySelector('.chat-box-header__options___nTsMU'),
  128. };
  129.  
  130. function addCSS(cssString) {
  131. const style = document.createElement('style');
  132. style.textContent = cssString;
  133. document.head.append(style);
  134. }
  135.  
  136. function getButtonConfigurations() {
  137. return JSON.parse(localStorage.getItem('chatButtonConfig')) || { buttons: [] };
  138. }
  139.  
  140. function saveButtonConfigurations(config) {
  141. localStorage.setItem('chatButtonConfig', JSON.stringify(config));
  142. }
  143.  
  144. function createUIPanel() {
  145. const panel = document.createElement('div');
  146. panel.className = 'custom-ui-panel';
  147. panel.innerHTML = `
  148. <h3>Chat Button Configuration</h3>
  149. <div id="button-configs"></div>
  150. <hr>
  151. <div>
  152. <input type="text" id="button-text" placeholder="Button Text">
  153. <label for="button-color">Background Color:</label>
  154. <input type="color" id="button-color">
  155. <select id="button-condition">
  156. <option value="TradeChat">Trade Chat</option>
  157. <option value="HospitalChat">Hospital Chat</option>
  158. <option value="FactionChat">Faction Chat</option>
  159. <option value="CompanyChat">Company Chat</option>
  160. <option value="GlobalChat">Global Chat</option>
  161. <option value="UserChat">User Chat</option>
  162. </select>
  163. <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>
  164. <button id="add-button">Add Button</button>
  165. <button id="edit-button" style="display: none;">Edit Button</button>
  166. </div>
  167. <button id="close-ui">Close</button>
  168. `;
  169. document.body.appendChild(panel);
  170.  
  171. document.getElementById('add-button').addEventListener('click', addNewButtonConfig);
  172. document.getElementById('edit-button').addEventListener('click', editButtonConfig);
  173. document.getElementById('close-ui').addEventListener('click', closeUI);
  174. populateButtonConfigs();
  175. }
  176.  
  177. function populateButtonConfigs() {
  178. const configsContainer = document.getElementById('button-configs');
  179. configsContainer.innerHTML = '';
  180. const configs = getButtonConfigurations();
  181.  
  182. configs.buttons.forEach((buttonConfig, index) => {
  183. const configDiv = document.createElement('div');
  184. configDiv.innerHTML = `
  185. <div>Text: ${buttonConfig.buttonText}</div>
  186. <div>Color: ${buttonConfig.backgroundColor}</div>
  187. <div>Condition: ${buttonConfig.condition}</div>
  188. <div>Message: ${buttonConfig.text}</div>
  189. `;
  190.  
  191. const editButton = document.createElement('button');
  192. editButton.textContent = 'Edit';
  193. editButton.addEventListener('click', () => selectForEdit(index));
  194. configDiv.appendChild(editButton);
  195.  
  196. const deleteButton = document.createElement('button');
  197. deleteButton.textContent = 'Delete';
  198. deleteButton.addEventListener('click', () => deleteButtonConfig(index));
  199. configDiv.appendChild(deleteButton);
  200.  
  201. configsContainer.appendChild(configDiv);
  202. });
  203. }
  204.  
  205. function selectForEdit(index) {
  206. const config = getButtonConfigurations().buttons[index];
  207. document.getElementById('button-text').value = config.buttonText;
  208. document.getElementById('button-color').value = config.backgroundColor;
  209. document.getElementById('button-condition').value = config.condition;
  210. document.getElementById('button-text-content').value = config.text;
  211.  
  212. document.getElementById('edit-button').style.display = 'block';
  213. document.getElementById('edit-button').setAttribute('data-edit-index', index);
  214. }
  215.  
  216. function deleteButtonConfig(index) {
  217. const config = getButtonConfigurations();
  218. config.buttons.splice(index, 1);
  219. saveButtonConfigurations(config);
  220. populateButtonConfigs();
  221. }
  222.  
  223. function addNewButtonConfig() {
  224. const buttonText = document.getElementById('button-text').value;
  225. const backgroundColor = document.getElementById('button-color').value;
  226. const condition = document.getElementById('button-condition').value;
  227. const text = document.getElementById('button-text-content').value;
  228.  
  229. const config = getButtonConfigurations();
  230. config.buttons.push({ buttonText, backgroundColor, condition, text });
  231. saveButtonConfigurations(config);
  232. populateButtonConfigs();
  233. }
  234.  
  235. function editButtonConfig() {
  236. const index = parseInt(document.getElementById('edit-button').getAttribute('data-edit-index'), 10);
  237. const buttonText = document.getElementById('button-text').value;
  238. const backgroundColor = document.getElementById('button-color').value;
  239. const condition = document.getElementById('button-condition').value;
  240. const text = document.getElementById('button-text-content').value;
  241.  
  242. const config = getButtonConfigurations();
  243. config.buttons[index] = { buttonText, backgroundColor, condition, text };
  244. saveButtonConfigurations(config);
  245. populateButtonConfigs();
  246. }
  247.  
  248. function closeUI() {
  249. document.querySelector('.custom-ui-panel').remove();
  250. }
  251.  
  252. function createConfigButton() {
  253. const settingsPanel = document.querySelector('.settings-panel___IZSDs');
  254. if (settingsPanel && !document.querySelector('#chat-config-button')) {
  255. const configButton = document.createElement('button');
  256. configButton.id = 'chat-config-button';
  257. configButton.textContent = 'Edit Chat Buttons';
  258. configButton.addEventListener('click', createUIPanel);
  259. settingsPanel.appendChild(configButton);
  260. }
  261. }
  262.  
  263. function applyButtonConfigurations() {
  264. const configs = getButtonConfigurations();
  265. document.querySelectorAll('.chat-box___mHm01').forEach(chatBox => {
  266. configs.buttons.forEach(buttonConfig => {
  267. const conditionFunc = conditions[buttonConfig.condition];
  268. if (conditionFunc && conditionFunc(chatBox) && !chatBox.querySelector(`[data-button-text="${buttonConfig.buttonText}"]`)) {
  269. const button = document.createElement('button');
  270. button.className = 'custom-chat-button';
  271. button.innerText = buttonConfig.buttonText;
  272. button.style.backgroundColor = buttonConfig.backgroundColor;
  273. button.setAttribute('data-button-text', buttonConfig.buttonText);
  274. button.addEventListener('click', (event) => addCustomText(chatBox, buttonConfig.text, event));
  275.  
  276. const filterContainer = chatBox.querySelector('.tt-chat-filter');
  277. filterContainer.insertBefore(button, filterContainer.firstChild);
  278. }
  279. });
  280. });
  281. }
  282.  
  283. function addCustomText(chatBox, messageTemplate, event) {
  284. const nameElement = chatBox.querySelector('.typography___Dc5WV');
  285. const name = nameElement ? nameElement.textContent.trim() : 'Trader';
  286. const message = messageTemplate.replace('{name}', name);
  287.  
  288. navigator.clipboard.writeText(message).then(() => {
  289. const textArea = chatBox.querySelector('textarea');
  290. textArea.focus();
  291. const startPos = textArea.selectionStart;
  292. const endPos = textArea.selectionEnd;
  293. textArea.setRangeText(message, startPos, endPos, 'end');
  294. textArea.dispatchEvent(new Event('input', { bubbles: true }));
  295. textArea.focus();
  296. textArea.selectionStart = textArea.selectionEnd = startPos + message.length;
  297. chatBox.querySelectorAll('.custom-chat-button').forEach(btn => {
  298. btn.classList.remove('recent');
  299. });
  300. event.target.classList.add('recent');
  301. });
  302. }
  303.  
  304. addCSS(buttonCSS);
  305.  
  306. const chatContainerObserver = new MutationObserver(function(mutations) {
  307. mutations.forEach(function(mutation) {
  308. createConfigButton();
  309. applyButtonConfigurations();
  310. });
  311. });
  312.  
  313. const chatContainer = document.querySelector('#chatRoot');
  314. if (chatContainer) {
  315. chatContainerObserver.observe(chatContainer, { childList: true, subtree: true });
  316. }
  317.  
  318. applyButtonConfigurations();
  319. })();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址