├── GPTSearch - Firefox ├── logo.png ├── manifest.json ├── background.js ├── popup.html └── popup.js ├── GPTSearch - Chrome ├── manifest.json ├── background.js ├── popup.html └── popup.js ├── LICENSE └── README.md /GPTSearch - Firefox/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bentlybro/GPTSearch/HEAD/GPTSearch - Firefox/logo.png -------------------------------------------------------------------------------- /GPTSearch - Chrome/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "manifest_version": 3, 3 | "name": "ChatGPT History Search", 4 | "version": "1.0", 5 | "permissions": [ 6 | "activeTab", 7 | "storage", 8 | "webRequest" 9 | ], 10 | "host_permissions": [ 11 | "https://chat.openai.com/*", 12 | "https://chatgpt.com/*" 13 | ], 14 | "action": { 15 | "default_popup": "popup.html" 16 | }, 17 | "background": { 18 | "service_worker": "background.js" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /GPTSearch - Firefox/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "manifest_version": 2, 3 | "name": "ChatGPT History Search", 4 | "version": "1.4", 5 | "permissions": [ 6 | "activeTab", 7 | "storage", 8 | "webRequest", 9 | "*://chat.openai.com/*", 10 | "*://chatgpt.com/*" 11 | ], 12 | "browser_action": { 13 | "default_popup": "popup.html", 14 | "default_icon": "logo.png" 15 | }, 16 | "background": { 17 | "scripts": ["background.js"], 18 | "persistent": false 19 | }, 20 | "icons": { 21 | "16": "logo.png", 22 | "48": "logo.png", 23 | "128": "logo.png" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Bently 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /GPTSearch - Chrome/background.js: -------------------------------------------------------------------------------- 1 | chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) { 2 | if (request.action === "fetchData") { 3 | chrome.storage.local.get(['apiKey'], function(result) { 4 | if (result.apiKey) { 5 | const apiKey = result.apiKey; 6 | const limit = 100; 7 | const maxOffset = 1000; 8 | let offset = 0; 9 | let allData = []; 10 | 11 | function fetchDataWithOffset() { 12 | if (offset <= maxOffset) { 13 | const url = `https://chatgpt.com/backend-api/conversations?offset=${offset}&limit=${limit}&order=updated`; 14 | 15 | fetch(url, { 16 | method: 'GET', 17 | headers: new Headers({ 18 | 'Authorization': apiKey, 19 | 'Content-Type': 'application/json' 20 | }), 21 | }) 22 | .then(response => response.json()) 23 | .then(data => { 24 | if (data && data.items) { 25 | allData = allData.concat(data.items); 26 | } 27 | offset += limit; 28 | 29 | if (offset <= maxOffset) { 30 | fetchDataWithOffset(); 31 | } else { 32 | sendResponse({ data: allData }); 33 | } 34 | }) 35 | .catch(error => { 36 | sendResponse({ data: error }); 37 | }); 38 | } 39 | } 40 | 41 | fetchDataWithOffset(); 42 | } else { 43 | sendResponse({ data: "API key not found in local storage" }); 44 | } 45 | }); 46 | 47 | return true; 48 | } 49 | }); 50 | -------------------------------------------------------------------------------- /GPTSearch - Firefox/background.js: -------------------------------------------------------------------------------- 1 | browser.runtime.onMessage.addListener(function (request, sender) { 2 | if (request.action === "fetchData") { 3 | return new Promise((resolve, reject) => { 4 | browser.storage.local.get(['apiKey']).then(result => { 5 | if (result.apiKey) { 6 | const apiKey = result.apiKey; 7 | const limit = 100; 8 | const maxOffset = 1000; 9 | let offset = 0; 10 | let allData = []; 11 | 12 | function fetchDataWithOffset() { 13 | if (offset <= maxOffset) { 14 | const url = `https://chatgpt.com/backend-api/conversations?offset=${offset}&limit=${limit}&order=updated`; 15 | 16 | fetch(url, { 17 | method: 'GET', 18 | headers: new Headers({ 19 | 'Authorization': apiKey, 20 | 'Content-Type': 'application/json' 21 | }), 22 | }) 23 | .then(response => response.json()) 24 | .then(data => { 25 | if (data && data.items) { 26 | allData = allData.concat(data.items); 27 | } 28 | offset += limit; 29 | 30 | if (offset <= maxOffset) { 31 | fetchDataWithOffset(); 32 | } else { 33 | resolve({ data: allData }); 34 | } 35 | }) 36 | .catch(error => { 37 | resolve({ data: error }); 38 | }); 39 | } 40 | } 41 | 42 | fetchDataWithOffset(); 43 | } else { 44 | resolve({ data: "API key not found in local storage" }); 45 | } 46 | }, error => { 47 | reject(error); 48 | }); 49 | }); 50 | } 51 | }); 52 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # GPTSearch - A ChatGPT Conversation History Search - Chrome & Firefox Extension 2 | 3 | GPTSearch revolutionizes the way users interact with their ChatGPT conversation history. Designed for simplicity and efficiency, it enables users to seamlessly search through their last 1000 conversation titles on ChatGPT. This tool is perfect for those who frequently use ChatGPT and need to reference past interactions quickly. 4 | 5 | ## Features 6 | 7 | - **Search Through 1000 Titles**: Easily navigate through the most recent 1000 conversation titles. 8 | - **Direct Conversation Access**: Click on a title to open the specific ChatGPT conversation. 9 | - **Automated Key Retrieval**: Use the "Get Key From Chat.OpenAI" button for automatic key retrieval and local storage. 10 | - **Data Fetching**: The "Fetch Data" button allows users to retrieve their last 1000 conversations. 11 | - **Convenient Search Bar**: Find specific conversations by typing their titles in the search bar. 12 | 13 | ## Installation 14 | 15 | ### For Chrome Users 16 | 1. Clone the repository: `git clone https://github.com/Bentlybro/GPTSearch.git` 17 | 2. Unzip the downloaded file. 18 | 3. Open Chrome and navigate to `chrome://extensions/`. 19 | 4. Enable 'Developer mode', click on "Load Unpacked", and select the unzipped "GPTSearch" folder. 20 | 21 | ### For Firefox Users 22 | Simply go to https://addons.mozilla.org/en-US/firefox/addon/chatgpt-history-search/ or https://addons.mozilla.org/en-US/firefox/addon/chatgpt-history-search-/?utm_source=addons.mozilla.org&utm_medium=referral&utm_content=search and click the "Add to Firefox" button to install the extension. 23 | 24 | ## Usage 25 | 26 | ### For Chrome Users 27 | - Open the Chrome extension. 28 | - Navigate to `https://chat.openai.com`. 29 | - Press the "Get Key From Chat.OpenAI" button to start using. 30 | - Simply press "Fetch Data" and wait for it to work 31 | 32 | ### For Firefox Users 33 | - After installation, the extension will be ready to use. 34 | - Navigate to `https://chat.openai.com` 35 | - Press the "Get Key From Chat.OpenAI" button to start using. 36 | - Simply press "Fetch Data" and wait for it to work 37 | 38 | ## Security and Privacy 39 | 40 | - When you press the "Get Key From Chat.OpenAI" button, it refreshes the Chat.OpenAI page and scans the network traffic to retrieve your user's "Authorization" key. 41 | - This key is then stored locally in your browser. 42 | - **Warning**: The "Authorization" key is used exclusively to access your conversation history. It is ONLY sent to OpenAI's API and is stored only locally. 43 | - We prioritize your privacy and security. Your key is never shared with any third parties. 44 | 45 | ## Note 46 | 47 | Currently, the extension is not available on the Chrome Store. It can be installed manually following the above steps. 48 | 49 | --- 50 | 51 | This tool is ideal for enhancing your ChatGPT experience, making it easier to revisit past conversations and manage your interaction history. 52 | --- 53 | [If You Like This Project Join My Discord Server](https://discord.gg/XbrtTTM2ZZ) 54 | --- 55 | ## What It Looks Like 56 | 57 | ![image](https://github.com/Bentlybro/GPTSearch/assets/27962737/0289d7af-7f55-418e-a86b-913121b5d05f) 58 | ![image](https://github.com/Bentlybro/GPTSearch/assets/27962737/a21cc8f3-a45f-4403-a107-ece1594a23e8) 59 | 60 | -------------------------------------------------------------------------------- /GPTSearch - Chrome/popup.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | API Results 5 | 101 | 102 | 103 | 104 | 105 | 106 | 107 |
108 |
109 |

Loading...

110 |

(This may take upwards of 10 seconds)

111 |
112 |
113 | 114 | 115 | 116 | 117 | -------------------------------------------------------------------------------- /GPTSearch - Firefox/popup.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | API Results 5 | 101 | 102 | 103 | 104 | 105 | 106 | 107 |
108 |
109 |

Loading...

110 |

(This may take upwards of 10 seconds)

111 |
112 |
113 | 114 | 115 | 116 | 117 | -------------------------------------------------------------------------------- /GPTSearch - Firefox/popup.js: -------------------------------------------------------------------------------- 1 | document.addEventListener('DOMContentLoaded', function() { 2 | browser.storage.local.get(['apiData']).then(result => { 3 | if (result.apiData) { 4 | document.getElementById('searchInput').style.display = 'block'; 5 | document.getElementById('clearDataButton').style.display = 'block'; 6 | displayData(result.apiData); 7 | } 8 | }); 9 | 10 | document.getElementById('getKeyButton').addEventListener('click', function() { 11 | getApiKey(); 12 | }); 13 | 14 | document.getElementById('searchInput').addEventListener('input', function() { 15 | browser.storage.local.get(['apiData']).then(result => { 16 | if (result.apiData) { 17 | displayData(result.apiData, document.getElementById('searchInput').value); 18 | } 19 | }); 20 | }); 21 | }); 22 | 23 | document.getElementById('fetchButton').addEventListener('click', function() { 24 | document.getElementById('loading').style.display = 'block'; 25 | browser.runtime.sendMessage({action: "fetchData"}).then(response => { 26 | document.getElementById('loading').style.display = 'none'; 27 | 28 | if (response.data) { 29 | document.getElementById('searchInput').style.display = 'block'; 30 | document.getElementById('clearDataButton').style.display = 'block'; 31 | browser.storage.local.set({apiData: response.data}); 32 | displayData(response.data); 33 | } else { 34 | document.getElementById('result').innerText = "Error fetching data."; 35 | } 36 | }); 37 | }); 38 | 39 | function displayData(data, filter = '') { 40 | if (data && Array.isArray(data)) { 41 | var items = data; 42 | var filteredItems = filter ? items.filter(function(item) { 43 | return item.title.toLowerCase().includes(filter.toLowerCase()); 44 | }) : items; 45 | 46 | if (filteredItems.length > 0) { 47 | var output = filteredItems.map(function(item) { 48 | return `${item.title}`; 49 | }).join(''); 50 | document.getElementById('result').innerHTML = output; 51 | } else { 52 | document.getElementById('result').innerHTML = "No matching data found."; 53 | } 54 | } else { 55 | document.getElementById('result').innerHTML = "No data to display."; 56 | } 57 | } 58 | 59 | let apiKeySaved = false; 60 | 61 | function getApiKey() { 62 | if (apiKeySaved) { 63 | alert('API key has already been saved.'); 64 | return; 65 | } 66 | 67 | browser.tabs.query({ active: true, currentWindow: true }).then(tabs => { 68 | const currentTab = tabs[0]; 69 | const currentUrl = new URL(currentTab.url); 70 | 71 | if (currentUrl.hostname !== 'chat.openai.com' && currentUrl.hostname !== 'chatgpt.com') { 72 | alert('Please use this on either "https://chat.openai.com" or "https://chatgpt.com" website'); 73 | return; 74 | } 75 | 76 | const onBeforeSendHeadersListener = function(details) { 77 | for (var i = 0; i < details.requestHeaders.length; ++i) { 78 | if (details.requestHeaders[i].name === 'Authorization') { 79 | var apiKey = details.requestHeaders[i].value; 80 | browser.storage.local.set({ apiKey: apiKey }).then(() => { 81 | alert('API key saved, You may now use Fetch Data!'); 82 | }); 83 | apiKeySaved = true; 84 | 85 | browser.webRequest.onBeforeSendHeaders.removeListener(onBeforeSendHeadersListener); 86 | } 87 | } 88 | }; 89 | 90 | browser.webRequest.onBeforeSendHeaders.addListener( 91 | onBeforeSendHeadersListener, 92 | { urls: ["https://chat.openai.com/*", "https://chatgpt.com/*"] }, 93 | ["requestHeaders"] 94 | ); 95 | 96 | browser.tabs.reload(currentTab.id); 97 | }); 98 | } 99 | 100 | document.getElementById('clearDataButton').addEventListener('click', function() { 101 | browser.storage.local.remove(['apiData']).then(() => { 102 | document.getElementById('result').innerHTML = ''; 103 | 104 | document.getElementById('searchInput').style.display = 'none'; 105 | document.getElementById('clearDataButton').style.display = 'none'; 106 | }).catch(error => { 107 | console.error(error); 108 | }); 109 | }); 110 | -------------------------------------------------------------------------------- /GPTSearch - Chrome/popup.js: -------------------------------------------------------------------------------- 1 | document.addEventListener('DOMContentLoaded', function() { 2 | chrome.storage.local.get(['apiData'], function(result) { 3 | if (result.apiData) { 4 | document.getElementById('searchInput').style.display = 'block'; 5 | document.getElementById('clearDataButton').style.display = 'block'; 6 | displayData(result.apiData); 7 | } 8 | }); 9 | 10 | document.getElementById('getKeyButton').addEventListener('click', function() { 11 | getApiKey(); 12 | }); 13 | 14 | document.getElementById('searchInput').addEventListener('input', function() { 15 | chrome.storage.local.get(['apiData'], function(result) { 16 | if (result.apiData) { 17 | displayData(result.apiData, document.getElementById('searchInput').value); 18 | } 19 | }); 20 | }); 21 | }); 22 | 23 | document.getElementById('fetchButton').addEventListener('click', function() { 24 | document.getElementById('loading').style.display = 'block'; 25 | chrome.runtime.sendMessage({action: "fetchData"}, function(response) { 26 | document.getElementById('loading').style.display = 'none'; 27 | 28 | if (response.data) { 29 | document.getElementById('searchInput').style.display = 'block'; 30 | document.getElementById('clearDataButton').style.display = 'block'; 31 | chrome.storage.local.set({apiData: response.data}, function() { 32 | }); 33 | displayData(response.data); 34 | } else { 35 | document.getElementById('result').innerText = "Error fetching data."; 36 | } 37 | }); 38 | }); 39 | 40 | function displayData(data, filter = '') { 41 | if (data && Array.isArray(data)) { 42 | var items = data; 43 | var filteredItems = filter ? items.filter(function(item) { 44 | return item.title.toLowerCase().includes(filter.toLowerCase()); 45 | }) : items; 46 | 47 | if (filteredItems.length > 0) { 48 | var output = filteredItems.map(function(item) { 49 | return `${item.title}`; 50 | }).join(''); 51 | document.getElementById('result').innerHTML = output; 52 | } else { 53 | document.getElementById('result').innerHTML = "No matching data found."; 54 | } 55 | } else { 56 | document.getElementById('result').innerHTML = "No data to display."; 57 | } 58 | } 59 | 60 | let apiKeySaved = false; 61 | 62 | function getApiKey() { 63 | if (apiKeySaved) { 64 | alert('API key has already been saved.'); 65 | return; 66 | } 67 | 68 | chrome.tabs.query({ active: true, currentWindow: true }, function(tabs) { 69 | const currentTab = tabs[0]; 70 | const currentUrl = new URL(currentTab.url); 71 | 72 | if (currentUrl.hostname !== 'chat.openai.com' && currentUrl.hostname !== 'chatgpt.com') { 73 | alert('Please use this on either "https://chat.openai.com" or "https://chatgpt.com" website'); 74 | return; 75 | } 76 | 77 | const onBeforeSendHeadersListener = function(details) { 78 | for (var i = 0; i < details.requestHeaders.length; ++i) { 79 | if (details.requestHeaders[i].name === 'Authorization') { 80 | var apiKey = details.requestHeaders[i].value; 81 | chrome.storage.local.set({ apiKey: apiKey }, function() { 82 | alert('API key saved, You may now use Fetch Data!'); 83 | }); 84 | apiKeySaved = true; 85 | 86 | chrome.webRequest.onBeforeSendHeaders.removeListener(onBeforeSendHeadersListener); 87 | } 88 | } 89 | }; 90 | 91 | chrome.webRequest.onBeforeSendHeaders.addListener( 92 | onBeforeSendHeadersListener, 93 | { urls: ["https://chat.openai.com/*", "https://chatgpt.com/*"] }, 94 | ["requestHeaders"] 95 | ); 96 | 97 | chrome.tabs.reload(currentTab.id); 98 | }); 99 | } 100 | 101 | document.getElementById('clearDataButton').addEventListener('click', function() { 102 | chrome.storage.local.remove(['apiData'], function() { 103 | var error = chrome.runtime.lastError; 104 | if (error) { 105 | console.error(error); 106 | } else { 107 | document.getElementById('result').innerHTML = ''; 108 | 109 | document.getElementById('searchInput').style.display = 'none'; 110 | document.getElementById('clearDataButton').style.display = 'none'; 111 | } 112 | }); 113 | }); 114 | --------------------------------------------------------------------------------