- // ==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';
- });
- }
- })();