您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Hover to reveal a grey trash‑can badge; click it to auto‑delete the conversation instantly (no confirmation popup).
// ==UserScript== // @name ChatGPT Quick‑Delete (No Popup) // @namespace https://chatgpt.com/ // @version 2.0 // @description Hover to reveal a grey trash‑can badge; click it to auto‑delete the conversation instantly (no confirmation popup). // @match https://chatgpt.com/* // @match https://chat.openai.com/* // @grant none // @author Blackupfreddy // @license CC-BY-NC-SA-4.0 // ==/UserScript== (() => { /* ─── 1. Acquire & cache bearer token ─────────────────────── */ async function getToken() { if (window.__QD_TOKEN) return window.__QD_TOKEN; // cached try { const r = await fetch('/api/auth/session', { credentials:'include' }); const data = await r.json(); if (data?.accessToken) { window.__QD_TOKEN = data.accessToken; return data.accessToken; } } catch {/* fall through */} console.warn('[QuickDelete] Unable to fetch accessToken'); return null; } /* ─── 2. Direct “hide” API call ───────────────────────────── */ async function apiHide(id) { const token = await getToken(); if (!token) throw new Error('no bearer token'); const res = await fetch(`/backend-api/conversation/${id}`, { method :'PATCH', credentials:'include', headers :{ 'Content-Type':'application/json', 'Authorization':`Bearer ${token}` }, body: JSON.stringify({ is_visible:false }) }); if (!res.ok) throw new Error(res.status); } /* ─── 3. Inject badge into each sidebar row ───────────────── */ const ICON = ` <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <polyline points="3 6 5 6 21 6"></polyline> <path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6 m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"></path> <line x1="10" y1="11" x2="10" y2="17"></line> <line x1="14" y1="11" x2="14" y2="17"></line> </svg>`; function addBadge(row) { if (row.querySelector('.quick-delete')) return; const id = row.getAttribute('href')?.match(/\/c\/([a-f0-9-]{36})/i)?.[1]; if (!id) return; row.style.position = 'relative'; const pad0 = parseFloat(getComputedStyle(row).paddingLeft) || 0; const badge = document.createElement('span'); badge.className = 'quick-delete'; badge.innerHTML = ICON; Object.assign(badge.style, { position:'absolute', left:'4px', top:'50%', transform:'translateY(-50%)', cursor:'pointer', zIndex:9, padding:'2px', borderRadius:'4px', background:'linear-gradient(135deg,var(--sidebar-surface-secondary,#4b5563),var(--sidebar-surface-tertiary,#6b7280))', color:'var(--token-text-primary)', opacity:0, transition:'opacity 120ms' }); badge.addEventListener('click', async e => { e.preventDefault(); e.stopImmediatePropagation(); badge.style.pointerEvents='none'; try { await apiHide(id); // talk to server row.style.transition='opacity .25s'; row.style.opacity='0'; setTimeout(()=>row.remove(),260); // remove from DOM } catch(err) { console.error('[QuickDelete] delete failed', err); badge.style.pointerEvents='auto'; } }, true); row.addEventListener('mouseenter', () => { badge.style.opacity='.85'; row.style.transition='padding-left 120ms'; row.style.paddingLeft=`${pad0 + 24}px`; }); row.addEventListener('mouseleave', () => { badge.style.opacity='0'; row.style.paddingLeft=`${pad0}px`; }); row.prepend(badge); } /* ─── 4. Observe sidebar for new rows ─────────────────────── */ const ROW = '#history a[draggable="true"][href^="/c/"]'; const observer = new MutationObserver(muts => muts.forEach(m => m.addedNodes.forEach(n => { if (n.nodeType!==1) return; if (n.matches(ROW)) addBadge(n); n.querySelectorAll?.(ROW).forEach(addBadge); }))); const init = setInterval(() => { const h = document.getElementById('history'); if (h) { clearInterval(init); observer.observe(h,{childList:true,subtree:true}); document.querySelectorAll(ROW).forEach(addBadge); console.log('[QuickDelete] ready'); } },150); })();