FaceDeer

Producer.ai Bulk Metadata Downloader

Feb 16th, 2026
235
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // ==UserScript==
  2. // @name         Producer.ai Project Batch Downloader (ZIP)
  3. // @namespace    http://tampermonkey.net/
  4. // @version      0.2
  5. // @description  Download all song metadata from a project page as a single ZIP
  6. // @match        https://www.producer.ai/project/*
  7. // @grant        none
  8. // @require      https://cdnjs.cloudflare.com/ajax/libs/jszip/3.10.1/jszip.min.js
  9. // ==/UserScript==
  10.  
  11. (function() {
  12.     'use strict';
  13.  
  14.     // --- Helper: sanitize filename ---
  15.     function sanitizeFilename(name) {
  16.         return name.replace(/[^a-z0-9_\-]+/gi, "_");
  17.     }
  18.  
  19.     // --- Extract song GUIDs from page ---
  20.     function getSongIdsFromLinks() {
  21.         const links = Array.from(document.querySelectorAll("a[href^='/song/']"));
  22.         const ids = new Set();
  23.         for (const link of links) {
  24.             const match = link.getAttribute("href").match(/\/song\/([a-f0-9-]+)/);
  25.             if (match) ids.add(match[1]);
  26.         }
  27.         return Array.from(ids);
  28.     }
  29.  
  30.     // --- Create button ---
  31.     const btn = document.createElement("button");
  32.     btn.textContent = "⬇️ Download All Songs (ZIP)";
  33.     btn.style.position = "fixed";
  34.     btn.style.top = "10px";
  35.     btn.style.right = "10px";
  36.     btn.style.zIndex = 9999;
  37.     btn.style.padding = "8px";
  38.     btn.style.background = "#673AB7";
  39.     btn.style.color = "white";
  40.     btn.style.border = "none";
  41.     btn.style.borderRadius = "4px";
  42.     btn.style.cursor = "pointer";
  43.     document.body.appendChild(btn);
  44.  
  45.     // --- Button click handler ---
  46.     btn.addEventListener("click", async () => {
  47.         const songIds = getSongIdsFromLinks();
  48.         if (songIds.length === 0) {
  49.             alert("No song links found on this page.");
  50.             return;
  51.         }
  52.  
  53.         try {
  54.             const response = await fetch("https://www.producer.ai/__api/v2/generations", {
  55.                 method: "POST",
  56.                 headers: { "Content-Type": "application/json" },
  57.                 body: JSON.stringify({ riff_ids: songIds })
  58.             });
  59.  
  60.             if (!response.ok) throw new Error("Network response was not ok");
  61.  
  62.             const json = await response.json();
  63.             const generations = json.generations || [];
  64.  
  65.             if (generations.length === 0) {
  66.                 alert("No generation data returned.");
  67.                 return;
  68.             }
  69.  
  70.             const zip = new JSZip();
  71.  
  72.             for (const gen of generations) {
  73.                 const title = gen.title ? sanitizeFilename(gen.title) : gen.id;
  74.                 const filename = `${title}.json`;
  75.                 zip.file(filename, JSON.stringify(gen, null, 2));
  76.             }
  77.  
  78.             // Generate ZIP and trigger download
  79.             const blob = await zip.generateAsync({ type: "blob" });
  80.             const url = URL.createObjectURL(blob);
  81.             const a = document.createElement("a");
  82.             a.href = url;
  83.             a.download = "project_songs.zip";
  84.             a.click();
  85.             URL.revokeObjectURL(url);
  86.  
  87.             alert(`Downloaded ${generations.length} songs into project_songs.zip`);
  88.  
  89.         } catch (err) {
  90.             console.error("Error fetching batch data:", err);
  91.             alert("Failed to fetch song data. See console for details.");
  92.         }
  93.     });
  94. })();
  95.  
Advertisement
Add Comment
Please, Sign In to add comment