This commit is contained in:
bob.rao
2023-04-14 15:59:21 +08:00
parent e6b5c6f0af
commit c766e8808c
6 changed files with 214 additions and 0 deletions

29
background.js Normal file
View File

@@ -0,0 +1,29 @@
chrome.webRequest.onCompleted.addListener(
(details) => {
if (
details.url.includes(
"https://chat.openai.com/backend-api/conversations?"
)
) {
chrome.tabs.sendMessage(details.tabId, {
message: "conversations_data_fetched",
});
}
},
{ urls: ["<all_urls>"] }
);
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
if (request.message === "fetch_conversations_data") {
fetch(request.url)
.then((response) => response.json())
.then((data) => {
sendResponse({ data: data.items });
})
.catch((error) => {
console.error("Error fetching conversations data:", error);
});
return true;
}
});

127
content.js Normal file
View File

@@ -0,0 +1,127 @@
console.log('content.js is running');
// 向每个会话前添加复选框
// 向每个会话前添加复选框
// function addCheckboxes() {
// const conversations = document.querySelectorAll(
// '.flex.flex-col.gap-2.pb-2.text-gray-100.text-sm > .flex.py-3.px-3.items-center.gap-3.relative.rounded-md.hover\\:bg-\\[\\#2A2B32\\].cursor-pointer.break-all.hover\\:pr-4.group'
// );
// conversations.forEach((conversation) => {
// const checkbox = document.createElement('input');
// checkbox.type = 'checkbox';
// checkbox.className = 'conversation-checkbox';
// conversation.insertBefore(checkbox, conversation.firstChild);
// });
// }
document.addEventListener("fetch", (event) => {
const response = event.detail.response;
if (response) {
console.log("Result found:", response);
// 在这里执行你的逻辑
}
});
function addCheckboxes() {
console.log(`try to addCheckboxes...`);
const conversations = document.querySelectorAll(
'.flex.flex-col.gap-2.pb-2.text-gray-100.text-sm > .flex.py-3.px-3.items-center.gap-3.relative.rounded-md.hover\\:bg-\\[\\#2A2B32\\].cursor-pointer.break-all.hover\\:pr-4.group'
);
conversations.forEach((conversation) => {
const checkbox = document.createElement('input');
checkbox.type = 'checkbox';
checkbox.className = 'conversation-checkbox';
checkbox.addEventListener('click', (event) => {
event.stopPropagation();
});
conversation.insertBefore(checkbox, conversation.firstChild);
});
}
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
if (request.message === 'add_checkboxes') {
addCheckboxes();
} else if (request.message === 'delete_selected_conversations') {
deleteSelectedConversations();
}
});
async function fetchAllConversations(offset = 0, limit = 20) {
const response = await fetch(
`https://chat.openai.com/backend-api/conversations?offset=${offset}&limit=${limit}`
);
const data = await response.json();
const conversations = data.items;
if (conversations.length === limit) {
const nextConversations = await fetchAllConversations(offset + limit, limit);
return [...conversations, ...nextConversations];
}
return conversations;
}
async function buildTitleToIdMap() {
const conversations = await fetchAllConversations();
const titleToIdMap = {};
conversations.forEach((conversation) => {
const title = conversation.title;
if (titleToIdMap[title]) {
titleToIdMap[title].push(conversation.id);
} else {
titleToIdMap[title] = [conversation.id];
}
});
return titleToIdMap;
}
async function deleteSelectedConversations() {
const titleToIdMap = await buildTitleToIdMap();
const checkboxes = document.querySelectorAll('.conversation-checkbox:checked');
const conversationIds = [];
checkboxes.forEach((checkbox) => {
const titleElement = checkbox.parentElement.querySelector('.text-ellipsis');
const title = titleElement.textContent;
const conversationId = titleToIdMap[title].shift();
if (conversationId) {
conversationIds.push(conversationId);
}
});
await Promise.all(
conversationIds.map(async (id) => {
console.log(`try to delete conversation with ID: ${id}`);
await fetch(`https://chat.openai.com/backend-api/conversation/${id}`, {
method: 'PATCH',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
status: 'deleted',
}),
});
console.log(`Deleted conversation with ID: ${id}`);
})
);
location.reload();
}

BIN
icon48.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

28
manifest.json Normal file
View File

@@ -0,0 +1,28 @@
{
"manifest_version": 2,
"name": "Bulk Delete ChatGPT Conversations",
"version": "1.0",
"description": "A Chrome extension to bulk delete ChatGPT conversations.",
"icons": {
"48": "icon48.png"
},
"permissions": [
"activeTab",
"storage",
"declarativeContent",
"webRequest",
"webRequestBlocking",
"<all_urls>"
],
"browser_action": {
"default_icon": "icon48.png",
"default_popup": "popup.html"
},
"content_scripts": [
{
"matches": ["https://chat.openai.com/*"],
"js": ["content.js"]
}
]
}

16
popup.html Normal file
View File

@@ -0,0 +1,16 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Bulk Delete ChatGPT Conversations</title>
</head>
<body>
<button id="add_checkboxes">添加复选框</button>
<button id="delete_selected">删除选中对话</button>
<script src="popup.js"></script>
<script src="content.js"></script>
<script src="background.js"></script>
</body>
</html>

14
popup.js Normal file
View File

@@ -0,0 +1,14 @@
// popup.js
document.getElementById('add_checkboxes').addEventListener('click', () => {
chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
chrome.tabs.sendMessage(tabs[0].id, { message: 'add_checkboxes' });
});
});
document.getElementById('delete_selected').addEventListener('click', () => {
chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
chrome.tabs.sendMessage(tabs[0].id, { message: 'delete_selected_conversations' });
});
});