Magnific.ai Batch Image Generator

Automates batch image generation on Magnific.ai with a sleek, toggleable popup.

// ==UserScript==
// @name         Magnific.ai Batch Image Generator
// @namespace    http://tampermonkey.net/
// @version      1.1
// @description  Automates batch image generation on Magnific.ai with a sleek, toggleable popup.
// @author       virtualdmns
// @match        https://magnific.ai/*
// @run-at       document-idle
// @license      MIT
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    // Function to create a delay
    function delay(ms) {
        return new Promise(resolve => setTimeout(resolve, ms));
    }

    // Create the toggle button
    const toggleButton = document.createElement('div');
    toggleButton.id = 'tm-batch-toggle';
    toggleButton.style = `
        position: fixed;
        right: 0;
        top: 50%;
        transform: translateY(-50%);
        background: #444;
        color: #fff;
        padding: 10px;
        cursor: pointer;
        z-index: 10000;
        border-radius: 5px 0 0 5px;
    `;
    toggleButton.textContent = 'Batch';
    document.body.appendChild(toggleButton);

    // Create the popup (hidden by default)
    const popup = document.createElement('div');
    popup.id = 'tm-batch-popup';
    popup.style = `
        position: fixed;
        right: 0;
        top: 0;
        width: 250px;
        height: 100%;
        background: #222;
        color: #fff;
        padding: 20px;
        box-shadow: -2px 0 5px rgba(0,0,0,0.5);
        z-index: 9999;
        display: none;
    `;
    popup.innerHTML = `
        <div style="text-align: right; margin-bottom: 10px;">
            <button id="tm-batch-close" style="background: none; border: none; color: #fff; font-size: 20px; cursor: pointer;">×</button>
        </div>
        <h3 style="margin: 0;">Batch Image Generator</h3>
        <textarea id="tm-batch-prompts" rows="10" style="width: 100%; background: #333; color: #fff; border: 1px solid #444; margin-top: 10px;"></textarea>
        <button id="tm-batch-start" style="background: #444; color: #fff; border: none; padding: 10px 20px; cursor: pointer; margin-top: 10px;">Start Generation</button>
        <div id="tm-batch-status" style="margin-top: 10px;">Status: Idle</div>
    `;
    document.body.appendChild(popup);

    // Toggle the popup with the button
    toggleButton.addEventListener('click', () => {
        popup.style.display = popup.style.display === 'none' ? 'block' : 'none';
    });

    // Close the popup with the × button
    document.getElementById('tm-batch-close').addEventListener('click', () => {
        popup.style.display = 'none';
    });

    // Get popup elements
    const promptsTextarea = document.getElementById('tm-batch-prompts');
    const startButton = document.getElementById('tm-batch-start');
    const statusDiv = document.getElementById('tm-batch-status');

    // Start button logic (unchanged, still spot on!)
    startButton.addEventListener('click', async () => {
        const siteTextarea = document.getElementById('text_paragraphMystic');
        const generateButton = document.getElementById('mystic-btn');

        if (!siteTextarea || !generateButton) {
            statusDiv.textContent = 'Error: Site elements not found.';
            return;
        }

        const prompts = promptsTextarea.value.split('\n').map(p => p.trim()).filter(p => p);
        if (prompts.length === 0) {
            statusDiv.textContent = 'Please enter some prompts.';
            return;
        }

        startButton.disabled = true;
        statusDiv.textContent = 'Processing...';

        for (let i = 0; i < prompts.length; i++) {
            const prompt = prompts[i];
            statusDiv.textContent = `Processing prompt ${i + 1} of ${prompts.length}`;
            siteTextarea.value = prompt;
            generateButton.click();
            await delay(1000);
        }

        statusDiv.textContent = 'Done';
        startButton.disabled = false;
    });
})();