您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Add label, UPC, and release dates to Deezer album pages
// ==UserScript== // @name Deezer Album Metadata Enhancer // @namespace http://tampermonkey.net/ // @version 1.0 // @description Add label, UPC, and release dates to Deezer album pages // @author waiter7 // @match https://www.deezer.com/*/album/* // @license MIT // @grant none // ==/UserScript== (function() { 'use strict'; function waitForElement(selector, timeout = 10000) { return new Promise((resolve, reject) => { const element = document.querySelector(selector); if (element) { resolve(element); return; } const observer = new MutationObserver((mutations, obs) => { const element = document.querySelector(selector); if (element) { obs.disconnect(); resolve(element); } }); observer.observe(document.body, { childList: true, subtree: true }); setTimeout(() => { observer.disconnect(); reject(new Error('Element not found within timeout')); }, timeout); }); } function formatDate(dateString) { if (!dateString) return 'N/A'; try { const date = new Date(dateString); return date.toLocaleDateString('en-US', { year: 'numeric', month: '2-digit', day: '2-digit' }); } catch (e) { return dateString; } } function extractAlbumId() { const path = window.location.pathname; const match = path.match(/\/album\/(\d+)/); return match ? match[1] : null; } function addMetadata() { try { // Get the album data from the global state const appState = window.__DZR_APP_STATE__; if (!appState || !appState.DATA) { console.log('No app state found, retrying...'); return false; } const albumData = appState.DATA; const albumId = extractAlbumId(); if (!albumId) { console.log('Could not extract album ID from URL'); return false; } // Extract metadata const label = albumData.LABEL_NAME || 'N/A'; const upc = albumData.UPC || 'N/A'; const digitalReleaseDate = formatDate(albumData.DIGITAL_RELEASE_DATE); const physicalReleaseDate = formatDate(albumData.PHYSICAL_RELEASE_DATE); const originalReleaseDate = formatDate(albumData.ORIGINAL_RELEASE_DATE); console.log('Album metadata:', { label, upc, digitalReleaseDate, physicalReleaseDate, originalReleaseDate }); // Find the existing metadata list (tracks/minutes/date/fans) const metadataList = document.querySelector('ul.css-1s16397'); if (!metadataList) { console.log('Metadata list not found'); return false; } // Check if our metadata is already added if (document.querySelector('.custom-metadata-table')) { console.log('Metadata already added'); return true; } // Create a clean table for metadata const tableContainer = document.createElement('div'); tableContainer.className = 'custom-metadata-table'; tableContainer.style.cssText = ` margin-top: 16px; background: #f8f9fa; border-radius: 8px; padding: 16px; border: 1px solid #e9ecef; `; const table = document.createElement('table'); table.style.cssText = ` width: 100%; border-collapse: separate; border-spacing: 0; font-size: 13px; color: #495057; `; // Create table header const thead = document.createElement('thead'); const headerRow = document.createElement('tr'); headerRow.style.borderBottom = '2px solid #dee2e6'; const headers = ['Label', 'UPC', 'Digital Release', 'Physical Release', 'Original Release', 'API']; headers.forEach(headerText => { const th = document.createElement('th'); th.textContent = headerText; th.style.cssText = ` text-align: left; padding: 8px 12px; font-weight: 600; color: #343a40; background: #e9ecef; border-right: 1px solid #dee2e6; `; if (headerText === 'API') { th.style.borderRight = 'none'; } headerRow.appendChild(th); }); thead.appendChild(headerRow); table.appendChild(thead); // Create table body const tbody = document.createElement('tbody'); const dataRow = document.createElement('tr'); dataRow.style.backgroundColor = '#ffffff'; const values = [label, upc, digitalReleaseDate, physicalReleaseDate, originalReleaseDate]; // Add data cells values.forEach((value, index) => { const td = document.createElement('td'); td.textContent = value || 'N/A'; td.style.cssText = ` padding: 12px; border-right: 1px solid #dee2e6; vertical-align: top; background: #ffffff; `; if (index === values.length - 1) { td.style.borderRight = 'none'; } dataRow.appendChild(td); }); // Add API link cell const apiTd = document.createElement('td'); apiTd.style.cssText = ` padding: 12px; vertical-align: top; background: #ffffff; text-align: center; `; const apiLink = document.createElement('a'); apiLink.href = `https://api.deezer.com/album/${albumId}`; apiLink.target = '_blank'; apiLink.textContent = 'View API'; apiLink.style.cssText = ` color: #a238ff; text-decoration: none; font-weight: 500; padding: 4px 8px; border-radius: 4px; background: #f8f5ff; border: 1px solid #a238ff; display: inline-block; transition: all 0.2s ease; `; apiLink.addEventListener('mouseenter', () => { apiLink.style.background = '#a238ff'; apiLink.style.color = '#ffffff'; }); apiLink.addEventListener('mouseleave', () => { apiLink.style.background = '#f8f5ff'; apiLink.style.color = '#a238ff'; }); apiTd.appendChild(apiLink); dataRow.appendChild(apiTd); tbody.appendChild(dataRow); table.appendChild(tbody); tableContainer.appendChild(table); // Insert the table after the existing metadata list metadataList.parentNode.insertBefore(tableContainer, metadataList.nextSibling); console.log('Metadata added successfully'); return true; } catch (error) { console.error('Error adding metadata:', error); return false; } } function init() { console.log('Deezer Album Metadata Enhancer: Starting...'); // Wait for the page to load and the metadata list to be available waitForElement('ul.css-1s16397') .then(() => { console.log('Metadata list found, attempting to add custom metadata...'); // Try to add metadata immediately if (!addMetadata()) { // If it fails, wait a bit for the app state to load setTimeout(() => { addMetadata(); }, 2000); } }) .catch(error => { console.error('Failed to find metadata list:', error); }); // Also listen for navigation changes (for SPA navigation) let lastUrl = location.href; new MutationObserver(() => { const url = location.href; if (url !== lastUrl) { lastUrl = url; if (url.includes('/album/')) { console.log('Navigation detected, re-initializing...'); setTimeout(init, 1000); } } }).observe(document, { subtree: true, childList: true }); } // Start when DOM is ready if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', init); } else { init(); } })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址