// ==UserScript== // @name MTA Nightly Builds - Copy Link to Newest // @namespace http://tampermonkey.net/ // @version 1.0.1 // @description Adds a button to copy the dynamic link to the newest nightly build for MTA:SA // @author SpeedyFolf // @match https://nightly.mtasa.com/* // @match https://nightly.multitheftauto.com/* // @grant none // @homepageURL https://github.com/SpeedyFolf/userscripts // @supportURL https://github.com/SpeedyFolf/userscripts/issues // @updateURL https://raw.githubusercontent.com/SpeedyFolf/userscripts/main/add-mta-nightly-builds-copy-link-to-newest-button.user.js // ==/UserScript== (function() { 'use strict'; // Map of version blocks and their respective dynamic latest links const buildLinks = { '1.7': { 'Windows nightly installer (Win10+)': 'https://nightly.mtasa.com/?mtasa-1.7-latest', 'Windows 64 bit server': 'https://nightly.mtasa.com/?mtasa_x64-1.7-latest', 'Windows arm64 server': 'https://nightly.mtasa.com/?mtasa_windows_arm64-1.7-latest', 'Linux 64 bit server': 'https://nightly.mtasa.com/?multitheftauto_linux_x64-1.7-latest', 'Linux arm64 server': 'https://nightly.mtasa.com/?multitheftauto_linux_arm64-1.7-latest' }, '1.6': { 'Windows nightly installer (Win10+)': 'https://nightly.mtasa.com/?mtasa-1.6-latest', 'Windows nightly installer (Win7/8/8.1)': 'https://nightly.mtasa.com/?mtasa_maetro-1.6-latest', 'Windows 64 bit server': 'https://nightly.mtasa.com/?mtasa_x64-1.6-latest', 'Windows arm64 server': 'https://nightly.mtasa.com/?mtasa_windows_arm64-1.6-latest', 'Linux 32 bit server': 'https://nightly.mtasa.com/?multitheftauto_linux-1.6-latest', 'Linux 64 bit server': 'https://nightly.mtasa.com/?multitheftauto_linux_x64-1.6-latest', 'Linux arm server': 'https://nightly.mtasa.com/?multitheftauto_linux_arm-1.6-latest', 'Linux arm64 server': 'https://nightly.mtasa.com/?multitheftauto_linux_arm64-1.6-latest' } }; let currentVersionContext = null; // Traverse all elements in document order (top-to-bottom) const allElements = document.querySelectorAll('*'); allElements.forEach(el => { // Extract direct text content to identify build titles const textContent = Array.from(el.childNodes) .filter(node => node.nodeType === Node.TEXT_NODE) .map(node => node.textContent.trim()) .join(' '); // Update the version context when a main version header is found if (textContent.includes('1.7 -')) { currentVersionContext = '1.7'; } else if (textContent.includes('1.6 -')) { currentVersionContext = '1.6'; } // If we are inside a known version block, look for build titles if (currentVersionContext && buildLinks[currentVersionContext]) { const exactMatchKey = Object.keys(buildLinks[currentVersionContext]).find(k => textContent === k); if (exactMatchKey) { // Ensure we don't append multiple buttons if the script re-runs if (!el.querySelector('.copy-latest-btn')) { const btn = document.createElement('button'); btn.className = 'copy-latest-btn'; btn.textContent = 'Copy link to newest'; // Layout adjustments btn.style.display = 'block'; // Moves the button beneath the build title btn.style.marginTop = '5px'; // Spacing above the button; half of table cell spacing btn.style.marginLeft = '16px'; // Indent to align with the box content btn.style.padding = '2px 6px'; btn.style.fontSize = '11px'; // Fixed width prevents layout shifting when the text changes to "Copied!" btn.style.width = '125px'; btn.style.textAlign = 'center'; btn.style.cursor = 'pointer'; const url = buildLinks[currentVersionContext][exactMatchKey]; // Copy to clipboard on click btn.addEventListener('click', (e) => { e.preventDefault(); navigator.clipboard.writeText(url).then(() => { const originalText = btn.textContent; btn.textContent = 'Copied!'; setTimeout(() => { btn.textContent = originalText; }, 2000); }); }); el.appendChild(btn); } } } }); })();