您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
VGMdb BBcode-style album information generator
当前为
// ==UserScript== // @name VGMdb Info Generator // @name:zh-CN VGMdb 信息生成 // @namespace https://vgmdb.net/ // @version 0.3.0 // @description VGMdb BBcode-style album information generator // @description:zh-cn VGMdb BBcode 样式专辑信息生成 // @author gkouen // @license MIT // @homepage https://blog.cya.moe/ // @match *://vgmdb.net/album/* // @icon https://vgmdb.net/favicon.ico // @grant GM_setClipboard // ==/UserScript== (function () { 'use strict'; const discussSpan = document.querySelector('span.label.smallfont > span#albumtools'); if (!discussSpan) return; // Info button const generateInfoButton = document.createElement('a'); generateInfoButton.textContent = 'Info'; generateInfoButton.style.cursor = 'pointer'; generateInfoButton.style.marginLeft = '0px'; generateInfoButton.style.color = '#ceffff'; generateInfoButton.addEventListener('click', (event) => { event.preventDefault(); event.stopPropagation(); generateInfo(); }); // Format button const formatButton = document.createElement('a'); formatButton.textContent = 'Format'; formatButton.style.cursor = 'pointer'; formatButton.style.marginLeft = '0px'; formatButton.style.color = '#ceffff'; formatButton.addEventListener('click', (event) => { event.preventDefault(); event.stopPropagation(); formatInfo(formatButton); }); const separator1 = document.createTextNode(' | '); const separator2 = document.createTextNode(' | '); discussSpan.appendChild(separator1); discussSpan.appendChild(generateInfoButton); discussSpan.appendChild(separator2); discussSpan.appendChild(formatButton); const months = { Jan: '01', Feb: '02', Mar: '03', Apr: '04', May: '05', Jun: '06', Jul: '07', Aug: '08', Sep: '09', Oct: '10', Nov: '11', Dec: '12' }; function generateInfo() { try { const coverArt = document.querySelector('#coverart').style.backgroundImage.match(/url\("?(.*?)"?\)/)?.[1]; const title = getAlbumTitle().replace(/^\s*\/|\/\s*$/g, ''); const catalogNumber = getSiblingValue('Catalog Number'); const releaseDate = getSiblingValue('Release Date'); const formattedDate = formatDate(releaseDate); const tracklistRows = document.querySelectorAll('#tracklist tr.rolebit'); const tracklist = Array.from(tracklistRows) .map(row => { const trackNumber = row.querySelector('.label')?.textContent.trim(); const trackName = row.querySelector('td[width="100%"]')?.textContent.trim(); return `${trackNumber}\t${trackName}`; }) .join('\n'); const resultText = `[quote] [img]${coverArt}[/img] [b]Title:[/b]${title} [b]Catalog number:[/b] ${catalogNumber} [b]Release date:[/b] ${formattedDate} [b]Tracklist[/b]: [code] ${tracklist} [/code] [/quote]`; showTemporaryModal(resultText); } catch (error) { console.error('Error:', error); alert('Error occurred, please check the console log!'); } } function formatInfo(buttonElement) { try { const title = getAlbumTitle(); const releaseDate = getSiblingValue('Release Date'); const formattedDate = formatDateForClipboard(releaseDate); const sanitizedTitle = sanitizeTitle(title); const formattedText = `[${formattedDate}]${sanitizedTitle}`; GM_setClipboard(formattedText); showTemporaryTooltip(buttonElement, 'Copied to clipboard'); } catch (error) { console.error('Error:', error); } } function getAlbumTitle() { const jpnTitle = document.querySelector('.albumtitle[lang="ja"]'); const engTitle = document.querySelector('.albumtitle[lang="en"]'); const title = jpnTitle?.textContent.trim() || eng?.textContent.trim() || 'Unknown'; return title; } function sanitizeTitle(title) { return title .replace(/^\s*\/|\/\s*$/g, '') .replace(/\//g, '/') .replace(/:/g, ':') .replace(/\*/g, '*') .replace(/\?/g, '?') .replace(/"/g, '"') .replace(/</g, '<') .replace(/>/g, '>') .replace(/\|/g, '|'); } function getSiblingValue(labelText) { const labelCell = Array.from(document.querySelectorAll('#album_infobit_large td')) .find(td => td.textContent.trim() === labelText); return labelCell ? labelCell.nextElementSibling.textContent.trim() : ''; } function formatDate(dateString) { if (!dateString) return 'Unknown Date'; const [month, day, year] = dateString.split(' '); return `${year}/${months[month]}/${day.replace(',', '')}`; } function formatDateForClipboard(dateString) { if (!dateString) return 'Unknown Date'; const [month, day, year] = dateString.split(' '); return `${year.substring(2)}${months[month]}${day.replace(',', '')}`; } function showTemporaryTooltip(buttonElement, message) { const tooltip = document.createElement('div'); tooltip.textContent = message; tooltip.style.position = 'absolute'; tooltip.style.backgroundColor = '#000'; tooltip.style.color = '#fff'; tooltip.style.padding = '5px 10px'; tooltip.style.borderRadius = '5px'; tooltip.style.fontSize = '12px'; tooltip.style.opacity = '0'; tooltip.style.transition = 'opacity 0.5s'; tooltip.style.zIndex = '1000'; const rect = buttonElement.getBoundingClientRect(); tooltip.style.left = `${rect.left + window.scrollX}px`; tooltip.style.top = `${rect.bottom + window.scrollY + 5}px`; document.body.appendChild(tooltip); requestAnimationFrame(() => { tooltip.style.opacity = '1'; }); setTimeout(() => { tooltip.style.opacity = '0'; setTimeout(() => { tooltip.remove(); }, 500); }, 500); } function showTemporaryModal(text) { const modal = document.createElement('div'); modal.style.position = 'fixed'; modal.style.top = '50%'; modal.style.left = '50%'; modal.style.transform = 'translate(-50%, -50%)'; modal.style.backgroundColor = '#fff'; modal.style.padding = '20px'; modal.style.boxShadow = '0 2px 10px rgba(0,0,0,0.2)'; modal.style.zIndex = '9999'; modal.style.opacity = '0'; modal.style.transition = 'opacity 0.5s'; const textarea = document.createElement('textarea'); textarea.style.width = '500px'; textarea.style.height = '300px'; textarea.textContent = text; const closeButton = document.createElement('button'); closeButton.textContent = 'Close'; closeButton.style.marginTop = '10px'; closeButton.addEventListener('click', () => { modal.style.opacity = '0'; setTimeout(() => { modal.remove(); }, 500); }); modal.appendChild(textarea); modal.appendChild(closeButton); document.body.appendChild(modal); requestAnimationFrame(() => { modal.style.opacity = '1'; }); } })();