Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // ==UserScript==
- // @name Producer.ai Metadata Downloader
- // @namespace http://tampermonkey.net/
- // @version 0.3
- // @description Add a button to download metadata JSON for the current song
- // @match https://www.producer.ai/*
- // @grant none
- // ==/UserScript==
- (function() {
- 'use strict';
- const BUTTON_ID = "producer-ai-download-btn";
- // --- Helper: extract GUID from URL ---
- function getSongId() {
- const match = window.location.pathname.match(/\/song\/([a-f0-9-]+)/);
- return match ? match[1] : null;
- }
- // --- Helper: sanitize filename ---
- function sanitizeFilename(name) {
- return name.replace(/[^a-z0-9_\-]+/gi, "_");
- }
- // --- Helper: download JSON as file ---
- function downloadJSON(data, filename) {
- const blob = new Blob([JSON.stringify(data, null, 2)], { type: "application/json" });
- const url = URL.createObjectURL(blob);
- const a = document.createElement("a");
- a.href = url;
- a.download = filename;
- document.body.appendChild(a);
- a.click();
- document.body.removeChild(a);
- URL.revokeObjectURL(url);
- }
- // --- Helper: Handle the actual API call ---
- async function handleDownload() {
- const songId = getSongId();
- if (!songId) {
- alert("Could not determine song ID from URL.");
- return;
- }
- const btn = document.getElementById(BUTTON_ID);
- if(btn) btn.textContent = "⏳ Fetching...";
- try {
- const response = await fetch("https://www.producer.ai/__api/v2/generations", {
- method: "POST",
- headers: { "Content-Type": "application/json" },
- body: JSON.stringify({ riff_ids: [songId] })
- });
- if (!response.ok) throw new Error("Network response was not ok");
- const json = await response.json();
- const generation = json.generations && json.generations[0];
- if (!generation) {
- alert("No generation data found in response.");
- return;
- }
- if (generation.id !== songId) {
- alert(`ID mismatch: expected ${songId}, got ${generation.id}`);
- return;
- }
- // Use title for filename if available
- const title = generation.title ? sanitizeFilename(generation.title) : songId;
- const filename = `${title}.json`;
- downloadJSON(generation, filename);
- } catch (err) {
- console.error("Error fetching lyric timing:", err);
- alert("Failed to fetch lyric timing JSON. See console for details.");
- } finally {
- if(btn) btn.textContent = "⬇️ Download Lyrics JSON";
- }
- }
- // --- Main Logic: Add Button if missing ---
- function checkAndAddButton() {
- // 1. Check if we are actually on a song page
- if (!getSongId()) {
- // Optional: Remove button if we navigate AWAY from a song page
- const existingBtn = document.getElementById(BUTTON_ID);
- if (existingBtn) existingBtn.remove();
- return;
- }
- // 2. Check if button already exists (prevent duplicates)
- if (document.getElementById(BUTTON_ID)) return;
- // 3. Create and append button
- const btn = document.createElement("button");
- btn.id = BUTTON_ID; // Important for tracking
- btn.textContent = "⬇️ Download Lyrics JSON";
- btn.style.position = "fixed";
- btn.style.top = "10px";
- btn.style.right = "10px";
- btn.style.zIndex = 9999;
- btn.style.padding = "8px";
- btn.style.background = "#4CAF50";
- btn.style.color = "white";
- btn.style.border = "none";
- btn.style.borderRadius = "4px";
- btn.style.cursor = "pointer";
- btn.onclick = handleDownload; // Attach the click handler
- document.body.appendChild(btn);
- }
- // --- SPA Observer ---
- // This watches the body for changes (navigation, rendering) and runs our check
- const observer = new MutationObserver(() => {
- checkAndAddButton();
- });
- // Start observing the document body for changes
- observer.observe(document.body, { childList: true, subtree: true });
- // Initial check in case the page is already loaded
- checkAndAddButton();
- })();
Advertisement
Add Comment
Please, Sign In to add comment