// ==UserScript== // @name Spotify链接及版权信息一键获取 // @namespace http://tampermonkey.net/ // @version 21.3 // @description 在Spotify页面获取链接和版权,在自定义页面粘贴信息 // @author Simon // @match https://open.spotify.com/* // @match https://beathamster.trialogger.com/* // @match https://beatdance.douyin.com/* // @grant GM_setClipboard // @grant GM_getValue // @grant GM_setValue // @grant GM_notification // @grant GM_addValueChangeListener // @grant GM_removeValueChangeListener // ==/UserScript== (function() { 'use strict'; const SPOTIFY_LOAD_DELAY = 5000; const CUSTOM_PAGE_DELAY = 2000; let storageListener = null; if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', function() { setTimeout(initInterface, getDelayTime()); }); } else { setTimeout(initInterface, getDelayTime()); } function getDelayTime() { const currentUrl = window.location.href; if (currentUrl.includes('open.spotify.com')) { return SPOTIFY_LOAD_DELAY; } else if (isTrialLoggerPage(currentUrl) || isDouyinPage(currentUrl)) { return CUSTOM_PAGE_DELAY; } return 2000; } function initInterface() { const currentUrl = window.location.href; const isSpotifyPage = currentUrl.includes('open.spotify.com'); const isCustomPage = isTrialLoggerPage(currentUrl) || isDouyinPage(currentUrl); removeLoadingIndicator(); if (storageListener) { GM_removeValueChangeListener(storageListener); storageListener = null; } if (isSpotifyPage) { if (isSpotifyReady()) { createSpotifyInterface(); autoFillSpotifyInfo(); setupStorageListener(); } else { showLoadingIndicator('等待Spotify加载完成...'); setTimeout(initInterface, 1000); } } else if (isCustomPage) { createCustomPageInterface(); autoFillCustomInfo(); setupStorageListener(); } } function setupStorageListener() { storageListener = GM_addValueChangeListener('spotify_link', function(name, oldValue, newValue, remote) { if (remote) { updateCustomInfo(); } }); GM_addValueChangeListener('spotify_copyright', function(name, oldValue, newValue, remote) { if (remote) { updateCustomInfo(); } }); } function updateCustomInfo() { const isCustomPage = isTrialLoggerPage(window.location.href) || isDouyinPage(window.location.href); if (isCustomPage) { const savedLink = GM_getValue('spotify_link', ''); const savedCopyright = GM_getValue('spotify_copyright', ''); const linkInput = document.getElementById('pasteLink'); const copyrightInput = document.getElementById('pasteCopyright'); if (linkInput && linkInput.value !== savedLink) { linkInput.value = savedLink; } if (copyrightInput && copyrightInput.value !== savedCopyright) { copyrightInput.value = savedCopyright; } } } function autoFillSpotifyInfo() { const currentUrl = window.location.href; const linkInput = document.getElementById('getLink'); if (linkInput) { linkInput.value = currentUrl; GM_setValue('spotify_link', currentUrl); } const copyrightText = extractCopyrightInfo(); const copyrightInput = document.getElementById('getCopyright'); if (copyrightInput) { copyrightInput.value = copyrightText; GM_setValue('spotify_copyright', copyrightText); } } function autoFillCustomInfo() { const savedLink = GM_getValue('spotify_link', ''); const savedCopyright = GM_getValue('spotify_copyright', ''); const linkInput = document.getElementById('pasteLink'); const copyrightInput = document.getElementById('pasteCopyright'); if (linkInput) linkInput.value = savedLink; if (copyrightInput) copyrightInput.value = savedCopyright; } function isSpotifyReady() { const copyrightElements = document.querySelectorAll( 'p.e-91000-text.encore-text-body-small[data-encore-id="text"], ' + 'p[data-encore-id="type"][dir="auto"], ' + '.Type__TypeElement-sc-goli3j-0.gBYjgG' ); return copyrightElements.length > 0 || document.querySelector('footer'); } function showLoadingIndicator(message) { removeLoadingIndicator(); const loader = document.createElement('div'); loader.id = 'spotify-manager-loader'; loader.style.position = 'fixed'; loader.style.top = '20px'; loader.style.right = '20px'; loader.style.zIndex = '10000'; loader.style.padding = '10px 15px'; loader.style.backgroundColor = '#1DB954'; loader.style.color = 'white'; loader.style.borderRadius = '5px'; loader.style.fontSize = '12px'; loader.style.boxShadow = '0 2px 10px rgba(0,0,0,0.3)'; loader.textContent = message; document.body.appendChild(loader); } function removeLoadingIndicator() { const existingLoader = document.getElementById('spotify-manager-loader'); if (existingLoader) existingLoader.remove(); } function isTrialLoggerPage(url) { return /^https:\/\/([a-zA-Z0-9-]+\.)?trialogger\.com\/.*/.test(url); } function isDouyinPage(url) { return /^https:\/\/beatdance\.douyin\.com\/.*/.test(url); } function createSpotifyInterface() { const container = createContainer('spotify'); const title = document.createElement('h4'); title.textContent = 'Spotify信息获取'; title.style.margin = '0 0 10px 0'; title.style.color = '#1DB954'; container.appendChild(title); const linkDiv = createInfoDisplay('链接:', 'getLink', '当前复制的链接', 'spotify'); container.appendChild(linkDiv); const copyrightDiv = createInfoDisplay('版权信息:', 'getCopyright', '当前复制的版权', 'spotify'); container.appendChild(copyrightDiv); const refreshButton = document.createElement('button'); refreshButton.textContent = '刷新信息(一键获取)'; refreshButton.style.padding = '8px 12px'; refreshButton.style.backgroundColor = '#1DB954'; refreshButton.style.color = 'white'; refreshButton.style.border = 'none'; refreshButton.style.borderRadius = '4px'; refreshButton.style.cursor = 'pointer'; refreshButton.style.fontSize = '12px'; refreshButton.style.marginTop = '10px'; refreshButton.style.width = '100%'; refreshButton.addEventListener('click', function() { autoFillSpotifyInfo(); showNotification('信息已刷新!'); }); container.appendChild(refreshButton); document.body.appendChild(container); setupSpotifyButtonEvents(); } function createCustomPageInterface() { const container = createContainer('custom'); const title = document.createElement('h4'); if (window.location.href.includes('trialogger.com')) { title.textContent = '信息粘贴'; title.style.color = '#FF6B35'; } else if (window.location.href.includes('douyin.com')) { title.textContent = '信息粘贴'; title.style.color = '#FE2C55'; } title.style.margin = '0 0 10px 0'; container.appendChild(title); const linkDiv = createInfoDisplay('链接:', 'pasteLink', '复制链接到剪切板', 'custom'); container.appendChild(linkDiv); const copyrightDiv = createInfoDisplay('版权信息:', 'pasteCopyright', '复制版权到剪切板', 'custom'); container.appendChild(copyrightDiv); const refreshButton = document.createElement('button'); refreshButton.textContent = '刷新信息'; refreshButton.style.padding = '8px 12px'; refreshButton.style.backgroundColor = window.location.href.includes('trialogger.com') ? '#FF6B35' : '#FE2C55'; refreshButton.style.color = 'white'; refreshButton.style.border = 'none'; refreshButton.style.borderRadius = '4px'; refreshButton.style.cursor = 'pointer'; refreshButton.style.fontSize = '12px'; refreshButton.style.marginTop = '10px'; refreshButton.style.width = '100%'; refreshButton.addEventListener('click', function() { autoFillCustomInfo(); showNotification('信息已刷新!'); }); container.appendChild(refreshButton); document.body.appendChild(container); setupCustomButtonEvents(); } function createInfoDisplay(labelText, inputId, buttonText, type) { const groupDiv = document.createElement('div'); groupDiv.style.marginBottom = '12px'; const label = document.createElement('label'); label.textContent = labelText; label.style.display = 'block'; label.style.marginBottom = '5px'; label.style.fontWeight = 'bold'; label.style.fontSize = '12px'; groupDiv.appendChild(label); const inputButtonDiv = document.createElement('div'); inputButtonDiv.style.display = 'flex'; inputButtonDiv.style.gap = '5px'; const input = document.createElement('input'); input.type = 'text'; input.id = inputId; input.style.flex = '1'; input.style.padding = '8px'; input.style.border = '1px solid ' + (type === 'spotify' ? '#1DB954' : '#ccc'); input.style.borderRadius = '4px'; input.style.fontSize = '12px'; input.style.readOnly = true; input.style.backgroundColor = '#f5f5f5'; input.style.cursor = 'default'; inputButtonDiv.appendChild(input); const button = document.createElement('button'); button.textContent = buttonText; button.style.padding = '8px 12px'; if (type === 'spotify') { button.style.backgroundColor = '#1DB954'; } else { button.style.backgroundColor = window.location.href.includes('trialogger.com') ? '#FF6B35' : '#FE2C55'; } button.style.color = 'white'; button.style.border = 'none'; button.style.borderRadius = '4px'; button.style.cursor = 'pointer'; button.style.fontSize = '12px'; button.style.whiteSpace = 'nowrap'; button.dataset.targetId = inputId; inputButtonDiv.appendChild(button); groupDiv.appendChild(inputButtonDiv); return groupDiv; } function createContainer(type) { const container = document.createElement('div'); container.id = 'spotify-manager-container'; container.style.position = 'fixed'; container.style.top = '20px'; container.style.right = '20px'; container.style.zIndex = '9999'; container.style.padding = '15px'; container.style.backgroundColor = '#f8f9fa'; container.style.border = '2px solid #ddd'; container.style.borderRadius = '10px'; container.style.boxShadow = '0 4px 12px rgba(0,0,0,0.15)'; container.style.minWidth = '300px'; container.style.maxWidth = '350px'; if (type === 'spotify') container.style.borderColor = '#1DB954'; else container.style.borderColor = window.location.href.includes('trialogger.com') ? '#FF6B35' : '#FE2C55'; return container; } function setupSpotifyButtonEvents() { const buttons = document.querySelectorAll('#spotify-manager-container button'); buttons[0].addEventListener('click', function() { const targetId = this.dataset.targetId; const input = document.getElementById(targetId); if (input && input.value) { GM_setClipboard(input.value); showNotification('链接已复制到剪贴板!'); } }); buttons[1].addEventListener('click', function() { const targetId = this.dataset.targetId; const input = document.getElementById(targetId); if (input && input.value) { GM_setClipboard(input.value); showNotification('版权信息已复制到剪贴板!'); } }); } function setupCustomButtonEvents() { const buttons = document.querySelectorAll('#spotify-manager-container button'); // 复制链接按钮 buttons[0].addEventListener('click', function() { const targetId = this.dataset.targetId; const input = document.getElementById(targetId); if (input && input.value) { GM_setClipboard(input.value); showNotification('链接已复制到剪贴板,请手动粘贴!'); } }); // 复制版权信息按钮 buttons[1].addEventListener('click', function() { const targetId = this.dataset.targetId; const input = document.getElementById(targetId); if (input && input.value) { GM_setClipboard(input.value); showNotification('版权信息已复制到剪贴板,请手动粘贴!'); } }); } function extractCopyrightInfo() { const selectors = [ 'p.e-91000-text.encore-text-body-small[data-encore-id="text"]', 'p[data-encore-id="type"][dir="auto"]', '.Type__TypeElement-sc-goli3j-0.gBYjgG', '[data-encore-id="text"]', '[data-encore-id="type"]' ]; const copyrightLines = []; for (const selector of selectors) { try { const elements = document.querySelectorAll(selector); for (const element of elements) { const text = element.textContent.trim(); if (text && (text.includes('©') || text.includes('℗') || /20\d{2}/.test(text) || /年/.test(text)) && text.length < 100) { if (!copyrightLines.includes(text)) { copyrightLines.push(text); } } } } catch (e) { continue; } } if (copyrightLines.length > 0) { return copyrightLines.slice(0, 3).join('\n'); } return "未找到版权信息"; } function showNotification(message) { GM_notification({ title: '操作成功', text: message, timeout: 2000, silent: true }); } })();