FaceDeer

Producer.ai Metadata Downloader

Nov 26th, 2025
681
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
JavaScript 4.45 KB | Source Code | 0 0
  1. // ==UserScript==
  2. // @name         Producer.ai Metadata Downloader
  3. // @namespace    http://tampermonkey.net/
  4. // @version      0.3
  5. // @description  Add a button to download metadata JSON for the current song
  6. // @match        https://www.producer.ai/*
  7. // @grant        none
  8. // ==/UserScript==
  9.  
  10. (function() {
  11.     'use strict';
  12.  
  13.     const BUTTON_ID = "producer-ai-download-btn";
  14.  
  15.     // --- Helper: extract GUID from URL ---
  16.     function getSongId() {
  17.         const match = window.location.pathname.match(/\/song\/([a-f0-9-]+)/);
  18.         return match ? match[1] : null;
  19.     }
  20.  
  21.     // --- Helper: sanitize filename ---
  22.     function sanitizeFilename(name) {
  23.         return name.replace(/[^a-z0-9_\-]+/gi, "_");
  24.     }
  25.  
  26.     // --- Helper: download JSON as file ---
  27.     function downloadJSON(data, filename) {
  28.         const blob = new Blob([JSON.stringify(data, null, 2)], { type: "application/json" });
  29.         const url = URL.createObjectURL(blob);
  30.         const a = document.createElement("a");
  31.         a.href = url;
  32.         a.download = filename;
  33.         document.body.appendChild(a);
  34.         a.click();
  35.         document.body.removeChild(a);
  36.         URL.revokeObjectURL(url);
  37.     }
  38.  
  39.     // --- Helper: Handle the actual API call ---
  40.     async function handleDownload() {
  41.         const songId = getSongId();
  42.         if (!songId) {
  43.             alert("Could not determine song ID from URL.");
  44.             return;
  45.         }
  46.  
  47.         const btn = document.getElementById(BUTTON_ID);
  48.         if(btn) btn.textContent = "⏳ Fetching...";
  49.  
  50.         try {
  51.             const response = await fetch("https://www.producer.ai/__api/v2/generations", {
  52.                 method: "POST",
  53.                 headers: { "Content-Type": "application/json" },
  54.                 body: JSON.stringify({ riff_ids: [songId] })
  55.             });
  56.  
  57.             if (!response.ok) throw new Error("Network response was not ok");
  58.  
  59.             const json = await response.json();
  60.             const generation = json.generations && json.generations[0];
  61.  
  62.             if (!generation) {
  63.                 alert("No generation data found in response.");
  64.                 return;
  65.             }
  66.  
  67.             if (generation.id !== songId) {
  68.                 alert(`ID mismatch: expected ${songId}, got ${generation.id}`);
  69.                 return;
  70.             }
  71.  
  72.             // Use title for filename if available
  73.             const title = generation.title ? sanitizeFilename(generation.title) : songId;
  74.             const filename = `${title}.json`;
  75.  
  76.             downloadJSON(generation, filename);
  77.  
  78.         } catch (err) {
  79.             console.error("Error fetching lyric timing:", err);
  80.             alert("Failed to fetch lyric timing JSON. See console for details.");
  81.         } finally {
  82.              if(btn) btn.textContent = "⬇️ Download Lyrics JSON";
  83.         }
  84.     }
  85.  
  86.     // --- Main Logic: Add Button if missing ---
  87.     function checkAndAddButton() {
  88.         // 1. Check if we are actually on a song page
  89.         if (!getSongId()) {
  90.             // Optional: Remove button if we navigate AWAY from a song page
  91.             const existingBtn = document.getElementById(BUTTON_ID);
  92.             if (existingBtn) existingBtn.remove();
  93.             return;
  94.         }
  95.  
  96.         // 2. Check if button already exists (prevent duplicates)
  97.         if (document.getElementById(BUTTON_ID)) return;
  98.  
  99.         // 3. Create and append button
  100.         const btn = document.createElement("button");
  101.         btn.id = BUTTON_ID; // Important for tracking
  102.         btn.textContent = "⬇️ Download Lyrics JSON";
  103.         btn.style.position = "fixed";
  104.         btn.style.top = "10px";
  105.         btn.style.right = "10px";
  106.         btn.style.zIndex = 9999;
  107.         btn.style.padding = "8px";
  108.         btn.style.background = "#4CAF50";
  109.         btn.style.color = "white";
  110.         btn.style.border = "none";
  111.         btn.style.borderRadius = "4px";
  112.         btn.style.cursor = "pointer";
  113.         btn.onclick = handleDownload; // Attach the click handler
  114.  
  115.         document.body.appendChild(btn);
  116.     }
  117.  
  118.     // --- SPA Observer ---
  119.     // This watches the body for changes (navigation, rendering) and runs our check
  120.     const observer = new MutationObserver(() => {
  121.         checkAndAddButton();
  122.     });
  123.  
  124.     // Start observing the document body for changes
  125.     observer.observe(document.body, { childList: true, subtree: true });
  126.  
  127.     // Initial check in case the page is already loaded
  128.     checkAndAddButton();
  129.  
  130. })();
Advertisement
Add Comment
Please, Sign In to add comment