Greasy Fork

Greasy Fork is available in English.

Prompt Your Grok Genius

L'estensione definitiva per gestire, organizzare e inviare i tuoi prompt su Grok.

当前为 2025-12-24 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         Prompt Your Grok Genius
// @namespace    http://tampermonkey.net/
// @version      1.0.0
// @description  L'estensione definitiva per gestire, organizzare e inviare i tuoi prompt su Grok.
// @author       Anam Orion
// @match        *://grok.com/*
// @match        *://x.com/i/grok*
// @icon         https://i.imgur.com/p26jpdo.png
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        GM_addStyle
// @license      MIT
// ==/UserScript==

(function() {
    'use strict';

    const DB_KEY = 'gpm_prompts_v2';
    let prompts = GM_getValue(DB_KEY) || GM_getValue('gpm_prompts') || [];

    const APP_ICON = `https://i.imgur.com/p26jpdo.png`;
    const COLORS = { DEFAULT: "#1d9bf0", PHOTO: "#f91880", VIDEO: "#7856ff", ALL: "#00ba7c", CLEAR: "#f44336" };
    const PALETTE = ["#1d9bf0", "#f91880", "#7856ff", "#00ba7c", "#ffa000", "#ffffff"];

    let lang = GM_getValue('gpm_lang', 'it');
    let currentSort = GM_getValue('gpm_sort_mode', 'recent');
    let currentMode = "ALL";
    let activeTagFilter = null;
    let editIdx = -1;
    let selectedColor = COLORS.DEFAULT;
    let fontSize = GM_getValue('gpm_font_size', 13);
    let isCompactView = GM_getValue('gpm_compact_view', false);

    const i18n = {
        it: { title: "PROMPT YOUR GROK GENIUS", search: "Cerca...", recent: "RECENTI", alpha: "A-Z", fav: "PREFERITI ❤️", newBtn: "+ NUOVO", save: "SALVA", cancel: "ANNULLA", charCount: "Caratteri", edit: "EDIT", del: "DEL", copy: "COPIA", repl: "REPL", send: "SEND", confirmDel: "Eliminare?", exp: "EXP", imp: "IMP", compact: "COMPACT", lang: "🇮🇹", tags: "Tag (es: cinematic, neon)", allTags: "TUTTI I TAG" },
        en: { title: "PROMPT YOUR GROK GENIUS", search: "Search...", recent: "RECENT", alpha: "A-Z", fav: "FAVORITES ❤️", newBtn: "+ NEW", save: "SAVE", cancel: "CANCEL", charCount: "Characters", edit: "EDIT", del: "DEL", copy: "COPY", repl: "REPL", send: "SEND", confirmDel: "Delete?", exp: "EXP", imp: "IMP", compact: "COMPACT", lang: "🇬🇧", tags: "Tags (eg: cinematic, neon)", allTags: "ALL TAGS" }
    };

    function t(key) { return i18n[lang][key]; }

    GM_addStyle(`
        #gpm-launcher { position: fixed !important; bottom: 25px; right: 25px; width: 62px; height: 62px; background: #000; border-radius: 14px; display: flex; align-items: center; justify-content: center; cursor: pointer; z-index: 2147483647; box-shadow: 0 0 10px rgba(29,155,240,0.5), 0 0 0 1px ${COLORS.DEFAULT}; background-image: url('${APP_ICON}'); background-size: cover; }
        #gpm-panel { position: fixed !important; bottom: 100px; right: 25px; width: 380px; height: 720px; background: #000; border: 1px solid ${COLORS.DEFAULT}; border-radius: 20px; z-index: 2147483646; display: none; flex-direction: column; color: #eff3f4; font-family: 'Inter', sans-serif; overflow: hidden; box-shadow: 0 0 20px rgba(29,155,240,0.3); }

        .gpm-header { padding: 12px 18px; border-bottom: 1px solid #333; display: flex; justify-content: space-between; align-items: center; }
        .gpm-content { flex: 1; overflow-y: auto; background: #000; }

        .gpm-item { padding: 12px 20px; border-bottom: 1px solid #2f3336; transition: background 0.1s; position: relative; }
        .gpm-item:nth-child(odd) { background: #0a0a0a; }
        .gpm-item:nth-child(even) { background: #121417; }
        .gpm-item:hover { background: #1f2124 !important; }

        .compact-mode .gpm-prompt-text, .compact-mode .gpm-char-count { display: none !important; }
        .compact-mode .gpm-item { padding: 10px 20px !important; }

        .media-btn { flex: 1; padding: 10px; border-radius: 8px; border: 1px solid #333; cursor: pointer; text-align: center; font-size: 11px; font-weight: 700; color: #71767b; transition: 0.2s; }
        .media-btn:hover { color: #fff; border-color: #555; }
        .media-btn.active.all { border-color: ${COLORS.ALL}; color: ${COLORS.ALL}; background: rgba(0,186,124,0.1); }
        .media-btn.active.photo { border-color: ${COLORS.PHOTO}; color: ${COLORS.PHOTO}; background: rgba(249,24,128,0.1); }
        .media-btn.active.video { border-color: ${COLORS.VIDEO}; color: ${COLORS.VIDEO}; background: rgba(120,86,255,0.1); }

        .sort-pill { background: #000; border: 1px solid #333; color: #71767b; padding: 8px; border-radius: 10px; font-size: 10px; cursor: pointer; text-align: center; font-weight: 700; flex: 1; transition: 0.2s; }
        .sort-pill:hover { color: #fff; border-color: #555; }
        .sort-pill.active { border-color: ${COLORS.DEFAULT}; color: ${COLORS.DEFAULT}; background: rgba(29, 155, 240, 0.15); }

        .act-link { font-size: 10px; font-weight: 800; color: #71767b; cursor: pointer; margin-right: 12px; text-transform: uppercase; transition: color 0.2s; display: inline-block; }
        .act-link:hover { color: #fff !important; }

        .clicked { opacity: 0.5; transform: scale(0.95); transition: 0.1s; }

        #gpm-editor { display: none; padding: 15px; flex-direction: column; height: 100%; background: #000; }
        #gpm-inp-text { width: 100%; background: #0a0a0a; border: 1px solid #333; color: #fff; border-radius: 12px; padding: 12px; resize: none; font-size: 14px; flex: 1; margin-bottom: 10px; outline: none; }
        .gpm-input { width: 100%; background: #111; border: 1px solid #333; color: #fff; border-radius: 10px; padding: 10px; margin-bottom: 8px; font-family: inherit; outline: none; }

        .color-dot { width: 26px; height: 26px; border-radius: 50%; cursor: pointer; border: 2px solid transparent; }
        .color-dot.active { border-color: #fff; transform: scale(1.1); }
    `);

    const panel = document.createElement('div');
    panel.id = 'gpm-panel';

    function initUI() {
        panel.innerHTML = `
            <div id="gpm-main-view" style="display:flex; flex-direction:column; height:100%;">
                <div class="gpm-header">
                    <div style="display:flex; align-items:center; gap:10px;">
                        <span id="lang-switcher" style="cursor:pointer; font-size:16px;">${t('lang')}</span>
                        <span id="font-dec" style="cursor:pointer; color:#71767b; font-size:14px;">A-</span>
                        <span id="font-inc" style="cursor:pointer; color:#71767b; font-size:14px;">A+</span>
                    </div>
                    <b style="font-size:10px; color:${COLORS.DEFAULT}; letter-spacing:1.5px; font-weight:900;">${t('title')}</b>
                    <span id="gpm-close" style="cursor:pointer; font-size:20px; color:#71767b;">✕</span>
                </div>
                <div class="media-switcher" style="display:flex; gap:8px; padding:10px 18px;">
                    <div class="media-btn" id="mode-all">🚀 ALL</div>
                    <div class="media-btn" id="mode-photo">📸 FOTO</div>
                    <div class="media-btn" id="mode-video">🎥 VIDEO</div>
                </div>
                <div style="padding: 0 18px 10px; display: flex; gap: 8px; align-items: center;">
                    <div id="gpm-clear-grok" class="sort-pill" style="max-width:42px; height:42px; display:flex; align-items:center; justify-content:center; font-size:16px; color:${COLORS.CLEAR};">🗑️</div>
                    <input type="text" id="gpm-search" class="gpm-input" style="flex:1; margin-bottom:0;" placeholder="${t('search')}">
                    <div id="tag-menu-btn" class="sort-pill" style="max-width:42px; height:42px; display:flex; align-items:center; justify-content:center; font-size:16px;">🏷️</div>
                </div>
                <div id="tag-dropdown" style="position:absolute; top:185px; right:18px; width:220px; max-height:250px; background:#16181c; border:1px solid ${COLORS.DEFAULT}; border-radius:12px; display:none; flex-direction:column; z-index:9999; overflow-y:auto;"></div>
                <div style="padding:0 18px 12px; display:flex; gap:6px;">
                    <div id="sort-recent" class="sort-pill">${t('recent')}</div>
                    <div id="sort-alpha" class="sort-pill">${t('alpha')}</div>
                    <div id="sort-fav" class="sort-pill">${t('fav')}</div>
                </div>
                <div class="gpm-content ${isCompactView ? 'compact-mode' : ''}" id="gpm-list"></div>
                <div style="padding:15px 18px; border-top:1px solid #333; display:flex; flex-wrap:wrap; gap:8px;">
                    <button id="gpm-add-new" style="flex:100%; background:#eff3f4; color:#000; border:none; padding:12px; border-radius:25px; font-weight:800; cursor:pointer; margin-bottom:5px;">${t('newBtn')}</button>
                    <button id="gpm-compact-toggle" class="sort-pill ${isCompactView?'active':''}" style="flex:1.5;">${t('compact')}</button>
                    <button id="gpm-export" class="sort-pill" style="flex:1;">${t('exp')}</button>
                    <button id="gpm-import-trigger" class="sort-pill" style="flex:1;">${t('imp')}</button>
                </div>
            </div>
            <div id="gpm-editor">
                 <div style="display:flex; justify-content:space-between; align-items:center; margin-bottom:10px;">
                    <b style="font-size:14px;">EDITOR</b>
                    <div id="gpm-editor-chars" style="font-size:11px; color:#71767b;">0 ${t('charCount')}</div>
                 </div>
                 <div id="color-picker" style="display:flex; gap:12px; margin-bottom:12px; justify-content:center;"></div>
                 <input type="text" id="gpm-inp-title" class="gpm-input" placeholder="Titolo">
                 <input type="text" id="gpm-inp-tags" class="gpm-input" placeholder="${t('tags')}">
                 <textarea id="gpm-inp-text" placeholder="Prompt..."></textarea>
                 <div style="display:flex; gap:10px; padding-top:5px;">
                    <button id="gpm-save" style="flex:1; background:${COLORS.DEFAULT}; color:white; border:none; padding:12px; border-radius:25px; font-weight:800; cursor:pointer;">${t('save')}</button>
                    <button id="gpm-cancel" style="flex:1; background:#16181c; color:white; border:none; padding:12px; border-radius:25px; cursor:pointer;">${t('cancel')}</button>
                 </div>
            </div>
            <input type="file" id="gpm-import-file" style="display:none;" accept=".json">
        `;
        setupEvents();
        render();
    }

    function setupEvents() {
        document.getElementById('gpm-close').onclick = togglePanel;
        document.getElementById('gpm-compact-toggle').onclick = (e) => { triggerFlash(e.currentTarget); isCompactView = !isCompactView; GM_setValue('gpm_compact_view', isCompactView); document.getElementById('gpm-list').classList.toggle('compact-mode'); e.currentTarget.classList.toggle('active'); render(); };
        document.getElementById('lang-switcher').onclick = () => { lang = (lang==='it'?'en':'it'); GM_setValue('gpm_lang', lang); initUI(); };
        document.getElementById('font-inc').onclick = () => { fontSize++; GM_setValue('gpm_font_size', fontSize); render(); };
        document.getElementById('font-dec').onclick = () => { fontSize--; GM_setValue('gpm_font_size', fontSize); render(); };
        document.getElementById('gpm-clear-grok').onclick = (e) => { triggerFlash(e.currentTarget); const box = document.querySelector('div[contenteditable="true"], textarea'); if(box) { box.innerHTML = ''; box.innerText = ''; if(box.value !== undefined) box.value = ''; box.focus(); } };
        document.getElementById('mode-all').onclick = () => { currentMode='ALL'; render(); };
        document.getElementById('mode-photo').onclick = () => { currentMode='PHOTO'; render(); };
        document.getElementById('mode-video').onclick = () => { currentMode='VIDEO'; render(); };
        document.getElementById('sort-recent').onclick = () => { currentSort='recent'; render(); };
        document.getElementById('sort-alpha').onclick = () => { currentSort='alpha'; render(); };
        document.getElementById('sort-fav').onclick = () => { currentSort='fav'; render(); };
        document.getElementById('gpm-export').onclick = (e) => { triggerFlash(e.currentTarget); const blob = new Blob([JSON.stringify(prompts)], {type: 'application/json'}); const a = document.createElement('a'); a.href = URL.createObjectURL(blob); a.download = 'grok_prompts.json'; a.click(); };
        document.getElementById('gpm-import-trigger').onclick = (e) => { triggerFlash(e.currentTarget); document.getElementById('gpm-import-file').click(); };
        document.getElementById('gpm-import-file').onchange = (e) => { const reader = new FileReader(); reader.onload = (ev) => { try { prompts = JSON.parse(ev.target.result); GM_setValue(DB_KEY, prompts); render(); } catch(err) { alert("Errore"); } }; reader.readAsText(e.target.files[0]); };
        document.getElementById('tag-menu-btn').onclick = (e) => { e.stopPropagation(); triggerFlash(e.currentTarget); const dd = document.getElementById('tag-dropdown'); dd.style.display = dd.style.display === 'flex' ? 'none' : 'flex'; updateTagDropdown(); };
        document.getElementById('gpm-add-new').onclick = (e) => { triggerFlash(e.currentTarget); apriEditor(); };
        document.getElementById('gpm-save').onclick = salvaPrompt;
        document.getElementById('gpm-cancel').onclick = chiudiEditor;
        document.getElementById('gpm-search').addEventListener('input', (e) => render(e.target.value.toLowerCase()));
    }

    function render(searchTerm = '') {
        const list = document.getElementById('gpm-list');
        if(!list) return;
        list.innerHTML = '';
        let listToDisplay = [...prompts];
        if (currentMode !== "ALL") listToDisplay = listToDisplay.filter(p => p.type === currentMode);
        if (activeTagFilter) listToDisplay = listToDisplay.filter(p => p.tags && p.tags.toLowerCase().includes(activeTagFilter));
        if (searchTerm) listToDisplay = listToDisplay.filter(p => p.title.toLowerCase().includes(searchTerm) || p.content.toLowerCase().includes(searchTerm));
        if (currentSort === 'alpha') listToDisplay.sort((a,b) => a.title.localeCompare(b.title));
        else if (currentSort === 'fav') listToDisplay.sort((a,b) => (b.fav?1:0) - (a.fav?1:0));
        else listToDisplay.sort((a,b) => (b.time || 0) - (a.time || 0));

        listToDisplay.forEach((p) => {
            const realIdx = prompts.indexOf(p);
            const div = document.createElement('div');
            div.className = 'gpm-item';
            div.innerHTML = `
                <div style="display:flex; justify-content:space-between; align-items:center;">
                    <span style="color:${p.color || COLORS.DEFAULT}; font-size:${fontSize+2}px; font-weight:800;">${p.title}</span>
                    <span id="fav-${realIdx}" style="color:${p.fav?'#f91880':'#333'}; font-size:16px; cursor:pointer;">❤</span>
                </div>
                <div class="gpm-char-count" style="color:#71767b; font-size:${fontSize-2}px; margin: 4px 0; font-weight:600;">${p.content.length} characters</div>
                <div class="gpm-prompt-text" style="color:#71767b; font-size:${fontSize}px; line-height:1.4; display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden; margin-bottom:10px;">${p.content}</div>
                <div style="display:flex; align-items:center; margin-top:5px;">
                   <span class="act-link" id="copy-${realIdx}">${t('copy')}</span>
                   <span class="act-link" id="repl-${realIdx}" style="color:#ffa000">${t('repl')}</span>
                   <span class="act-link" id="edit-${realIdx}">${t('edit')}</span>
                   <span class="act-link" id="del-${realIdx}" style="color:#f44336">${t('del')}</span>
                   <span class="act-link" id="send-${realIdx}" style="color:#00ba7c; font-size:16px; margin-left:auto;">🚀</span>
                </div>
            `;
            list.appendChild(div);

            const bindAct = (id, fn) => { const el = document.getElementById(id); if(el) el.onclick = (e) => { e.stopPropagation(); triggerFlash(el); fn(); }; };
            bindAct(`copy-${realIdx}`, () => navigator.clipboard.writeText(p.content));
            bindAct(`edit-${realIdx}`, () => apriEditor(realIdx));
            bindAct(`del-${realIdx}`, () => { if(confirm(t('confirmDel'))) { prompts.splice(realIdx,1); GM_setValue(DB_KEY, prompts); render(); } });
            bindAct(`fav-${realIdx}`, () => { prompts[realIdx].fav = !prompts[realIdx].fav; GM_setValue(DB_KEY, prompts); render(); });
            bindAct(`repl-${realIdx}`, () => inserisci(p.content, true));
            bindAct(`send-${realIdx}`, () => { inserisci(p.content); setTimeout(() => { const btn = document.querySelector('button[aria-label*="Send"], button[type="submit"]'); if(btn) btn.click(); }, 150); });
        });
        updateTabUI();
    }

    function updateTagDropdown() {
        const dropdown = document.getElementById('tag-dropdown');
        const stats = {};
        prompts.forEach(p => { if(p.tags) p.tags.split(',').forEach(t => { const tag = t.trim().toLowerCase(); if(tag) stats[tag] = (stats[tag] || 0) + 1; }); });
        let html = `<div class="tag-opt" id="filter-tag-clear" style="padding:12px; cursor:pointer; color:${COLORS.DEFAULT}">× ${t('allTags')}</div>`;
        Object.keys(stats).sort().forEach(tag => { html += `<div class="tag-opt" data-tag="${tag}" style="padding:12px; cursor:pointer; border-bottom:1px solid #222; display:flex; justify-content:space-between;"><span>#${tag}</span><span style="opacity:0.5;">${stats[tag]}</span></div>`; });
        dropdown.innerHTML = html;
        dropdown.querySelectorAll('.tag-opt').forEach(opt => { opt.onclick = (e) => { e.stopPropagation(); activeTagFilter = opt.getAttribute('data-tag'); dropdown.style.display = 'none'; render(); }; });
    }

    function apriEditor(idx = -1) {
        editIdx = idx;
        document.getElementById('gpm-main-view').style.display = 'none';
        document.getElementById('gpm-editor').style.display = 'flex';
        const p = prompts[idx] || {title:'', content:'', tags:'', color: COLORS.DEFAULT};
        document.getElementById('gpm-inp-title').value = p.title;
        document.getElementById('gpm-inp-text').value = p.content;
        document.getElementById('gpm-inp-tags').value = p.tags || '';
        document.getElementById('gpm-editor-chars').innerText = `${p.content.length} ${t('charCount')}`;
        selectedColor = p.color || COLORS.DEFAULT;
        const cp = document.getElementById('color-picker'); cp.innerHTML = '';
        PALETTE.forEach(c => {
            const dot = document.createElement('div');
            dot.className = `color-dot ${c === selectedColor ? 'active' : ''}`;
            dot.style.backgroundColor = c;
            dot.onclick = () => { selectedColor = c; document.querySelectorAll('.color-dot').forEach(d => d.classList.remove('active')); dot.classList.add('active'); };
            cp.appendChild(dot);
        });
    }

    function salvaPrompt() {
        const tVal = document.getElementById('gpm-inp-title').value.trim();
        const cVal = document.getElementById('gpm-inp-text').value.trim();
        if(!tVal || !cVal) return;
        const newObj = { title: tVal, content: cVal, tags: document.getElementById('gpm-inp-tags').value, type: currentMode, color: selectedColor, time: Date.now(), fav: (editIdx>-1 ? prompts[editIdx].fav : false) };
        if(editIdx > -1) prompts[editIdx] = newObj; else prompts.push(newObj);
        GM_setValue(DB_KEY, prompts); chiudiEditor(); render();
    }

    function updateTabUI() {
        document.querySelectorAll('.media-btn').forEach(b => b.classList.remove('active', 'all', 'photo', 'video'));
        const mBtn = document.getElementById(`mode-${currentMode.toLowerCase()}`);
        if(mBtn) mBtn.classList.add('active', currentMode.toLowerCase());
        document.querySelectorAll('.sort-pill').forEach(b => b.classList.remove('active'));
        const sBtn = document.getElementById(`sort-${currentSort}`);
        if(sBtn) sBtn.classList.add('active');
    }

    function chiudiEditor() { document.getElementById('gpm-main-view').style.display='flex'; document.getElementById('gpm-editor').style.display='none'; }
    function triggerFlash(el) { el.classList.add('clicked'); setTimeout(() => el.classList.remove('clicked'), 150); }
    function togglePanel() { panel.style.display = panel.style.display === 'flex' ? 'none' : 'flex'; }
    function inserisci(testo, replace = false) {
        const box = document.querySelector('div[contenteditable="true"], textarea');
        if (box) { box.focus(); if(replace) { box.innerHTML = ''; box.innerText = ''; if(box.value !== undefined) box.value = ''; } document.execCommand('insertText', false, testo); }
    }

    document.body.appendChild(panel);
    const launcher = document.createElement('div');
    launcher.id = 'gpm-launcher';
    launcher.onclick = togglePanel;
    document.body.appendChild(launcher);
    initUI();
})();