您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Adds checkboxes to ChatGPT conversations, and a button to batch delete them. Requires manual input of Auth token - take it from any valid request headers.
// ==UserScript== // @name Batch delete for ChatGPT // @namespace Violentmonkey Scripts // @match *://chatgpt.com/* // @grant none // @license MIT // @version 1.0 // @author m3 // @description Adds checkboxes to ChatGPT conversations, and a button to batch delete them. Requires manual input of Auth token - take it from any valid request headers. // ==/UserScript== (function () { 'use strict'; let bearerToken = null; function askForToken() { bearerToken = prompt('Paste your Bearer token (only used locally for making delete requests)'); } function refreshSidebar() { const sidebar = document.querySelector('#history'); if (sidebar) { location.reload(); } } function delay(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } function addDeleteButton() { const heading = document.querySelector('#history h2'); if (!heading || document.querySelector('#vm-delete-btn')) return; const wrapper = document.createElement('span'); wrapper.style.display = 'inline-flex'; wrapper.style.alignItems = 'center'; wrapper.style.gap = '8px'; const btn = document.createElement('button'); btn.id = 'vm-delete-btn'; btn.textContent = 'Delete marked'; Object.assign(btn.style, { backgroundColor: '#e53935', color: 'white', border: 'none', margin: '0 10px', padding: '4px 8px', borderRadius: '4px', cursor: 'pointer' }); const progress = document.createElement('span'); progress.id = 'vm-progress'; progress.style.fontSize = '0.9em'; progress.style.color = '#888'; wrapper.appendChild(btn); wrapper.appendChild(progress); heading.appendChild(wrapper); btn.addEventListener('click', async () => { const checked = document.querySelectorAll('.vm-checkbox:checked'); const ids = [...checked].map(cb => cb.dataset.chatId); if (!ids.length) return; const confirmed = confirm(`Really delete ${ids.length} conversation(s)?`); if (!confirmed) return; if (!bearerToken) askForToken(); if (!bearerToken) { alert('Bearer token is required.'); return; } const cleanToken = bearerToken.startsWith('Bearer ') ? bearerToken.slice(7) : bearerToken; progress.textContent = `0 / ${ids.length}`; for (let i = 0; i < ids.length; i++) { const id = ids[i]; try { const res = await fetch(`https://chatgpt.com/backend-api/conversation/${id}`, { method: 'PATCH', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${bearerToken}` }, body: JSON.stringify({ is_visible: false }) }); if (res.ok) { console.log(`Deleted: ${id}`); } else { console.warn(`Failed: ${id}`, res.status); } } catch (err) { console.error(`Error: ${id}`, err); } progress.textContent = `${i + 1} / ${ids.length}`; await delay(250); } progress.textContent = 'Done!'; await delay(3000); refreshSidebar(); }); } function addCheckboxes() { const chatItems = document.querySelectorAll('#history a[href^="/c/"]'); chatItems.forEach(item => { if (item.querySelector('.vm-checkbox')) return; const chatId = item.getAttribute('href').split('/c/')[1]; const checkbox = document.createElement('input'); checkbox.type = 'checkbox'; checkbox.className = 'vm-checkbox'; checkbox.style.marginRight = '6px'; checkbox.dataset.chatId = chatId; checkbox.addEventListener('click', e => { e.stopPropagation(); }); const titleSpan = item.querySelector('span'); if (titleSpan) { titleSpan.parentElement.insertBefore(checkbox, titleSpan); } }); } const observer = new MutationObserver(() => { addDeleteButton(); addCheckboxes(); }); observer.observe(document.body, { childList: true, subtree: true }); addDeleteButton(); addCheckboxes(); })();