您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Add Free Download buttons to Blendermarket products.
当前为
// ==UserScript== // @name Free Blendermarket Downloader // @description Add Free Download buttons to Blendermarket products. // @icon https://assets.superhivemarket.com/site_assets/images/black_bee.png // @version 1.2 // @author afkarxyz // @namespace https://github.com/afkarxyz/misc-scripts/ // @supportURL https://github.com/afkarxyz/misc-scripts/issues // @license MIT // @match https://blendermarket.com/* // @grant none // @run-at document-idle // ==/UserScript== (function() { 'use strict'; let lastUrl = location.href; let observer = null; let buttonCheckInterval = null; let retryCount = 0; const MAX_RETRIES = 10; const RETRY_DELAY = 500; function getProductNameFromURL() { const currentURL = window.location.href; const match = currentURL.match(/products\/([^/?]+)/); if (match) { return match[1]; } return ''; } function createCGDownloadURL(productName) { return `https://cgdownload.ru/?s=${encodeURIComponent(productName.replace(/-/g, ' '))}`; } function createGFXCampURL(productName) { return `https://www.gfxcamp.com/${productName}/`; } function clearExistingButtons() { const existingButtons = document.querySelectorAll('.cgdownload-button, .gfxcamp-button'); existingButtons.forEach(button => button.remove()); } function createButtonContent(iconUrl, text) { const container = document.createElement('div'); container.style.display = 'flex'; container.style.alignItems = 'center'; container.style.justifyContent = 'center'; container.style.gap = '8px'; const img = document.createElement('img'); img.src = iconUrl; img.style.height = '20px'; img.style.width = '20px'; img.alt = `${text} Icon`; const span = document.createElement('span'); span.textContent = text; container.appendChild(img); container.appendChild(span); return container; } function createDownloadButton(className, iconUrl, buttonText, urlCreator) { const button = document.createElement('button'); button.className = `btn btn-primary d-grid btn-lg shadow w-100 mt-2 ${className}`; button.appendChild(createButtonContent(iconUrl, buttonText)); button.addEventListener('click', function(e) { e.preventDefault(); const productName = getProductNameFromURL(); if (productName) { const downloadURL = urlCreator(productName); window.open(downloadURL, '_blank'); } }); return button; } function addDownloadButtons() { if (!window.location.href.includes('/products/')) { return false; } clearExistingButtons(); const originalForm = document.querySelector('.button_to'); if (!originalForm) { return false; } if (document.querySelector('.cgdownload-button') && document.querySelector('.gfxcamp-button')) { return true; } const cgDownloadButton = createDownloadButton( 'cgdownload-button', 'https://cgdownload.ru/wp-content/themes/dark/images/mstile-150x150.png', 'Free Download', createCGDownloadURL ); const gfxCampButton = createDownloadButton( 'gfxcamp-button', 'https://www.gfxcamp.com/images/60.jpg', 'Free Download', createGFXCampURL ); originalForm.insertAdjacentElement('afterend', gfxCampButton); originalForm.insertAdjacentElement('afterend', cgDownloadButton); return true; } function startButtonCheck() { if (buttonCheckInterval) { clearInterval(buttonCheckInterval); } retryCount = 0; buttonCheckInterval = setInterval(() => { if (addDownloadButtons() || retryCount >= MAX_RETRIES) { clearInterval(buttonCheckInterval); buttonCheckInterval = null; retryCount = 0; } else { retryCount++; } }, RETRY_DELAY); } function startObserver() { if (observer) { observer.disconnect(); } startButtonCheck(); observer = new MutationObserver((mutations) => { const hasRelevantChanges = mutations.some(mutation => { const addedNodes = Array.from(mutation.addedNodes); return addedNodes.some(node => { if (node.nodeType === Node.ELEMENT_NODE) { return node.querySelector('.button_to') || node.classList.contains('button_to') || node.closest('.button_to'); } return false; }); }); if (hasRelevantChanges) { startButtonCheck(); } }); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['class', 'style'], characterData: false }); } function setupHistoryListener() { const pushState = history.pushState; history.pushState = function() { pushState.apply(history, arguments); setTimeout(startObserver, 100); }; const replaceState = history.replaceState; history.replaceState = function() { replaceState.apply(history, arguments); setTimeout(startObserver, 100); }; window.addEventListener('popstate', () => setTimeout(startObserver, 100)); } if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', () => { setupHistoryListener(); startObserver(); }); } else { setupHistoryListener(); startObserver(); } setInterval(() => { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(startObserver, 100); } }, 100); })();