Functional scraping of the project page sans files.txt
This commit is contained in:
@ -2,7 +2,7 @@ browser.browserAction.onClicked.addListener((tab) => {
|
||||
console.log('Extension clicked - triggering artifact collection.');
|
||||
|
||||
// Check if we're on the correct domain and path
|
||||
if (!tab.url.startsWith('https://claude.ai/chat/')) {
|
||||
if (!tab.url.startsWith('https://claude.ai/chat') && !tab.url.startsWith('https://claude.ai/project')) {
|
||||
console.log('Not on claude.ai chat page');
|
||||
return;
|
||||
}
|
||||
|
||||
114
src/scraper.js
114
src/scraper.js
@ -234,18 +234,124 @@ const ChatArtifactScraper = {
|
||||
};
|
||||
|
||||
const ProjectArtifactScraper = {
|
||||
getArtifactListItems() {
|
||||
const gridContainer = document.querySelector('ul.grid');
|
||||
const artifactHash = {};
|
||||
|
||||
if (!gridContainer) {
|
||||
return artifactHash;
|
||||
}
|
||||
|
||||
gridContainer.querySelectorAll('h3').forEach((titleElement) => {
|
||||
const filename = titleElement.textContent.trim();
|
||||
artifactHash[filename] = false;
|
||||
});
|
||||
|
||||
return artifactHash;
|
||||
},
|
||||
|
||||
getArtifact(filename, isCurrentlySelected) {
|
||||
return new Promise((resolve, reject) => {
|
||||
// Find the h3 element with the matching filename
|
||||
const gridContainer = document.querySelector('ul.grid');
|
||||
if (!gridContainer) {
|
||||
reject(new Error('Grid container not found'));
|
||||
return;
|
||||
}
|
||||
|
||||
let targetButton = null;
|
||||
gridContainer.querySelectorAll('h3').forEach((titleElement) => {
|
||||
if (titleElement.textContent.trim() === filename) {
|
||||
// Find the clickable button that contains this h3
|
||||
targetButton = titleElement.closest('button');
|
||||
}
|
||||
});
|
||||
|
||||
if (!targetButton) {
|
||||
reject(new Error(`Could not find file button for: ${filename}`));
|
||||
return;
|
||||
}
|
||||
|
||||
// Click the button to open the file modal
|
||||
targetButton.click();
|
||||
|
||||
// Wait for modal to appear and extract content
|
||||
let attempts = 0;
|
||||
const maxAttempts = 30; // 3 seconds total
|
||||
|
||||
const handleModal = () => {
|
||||
// Look for the modal dialog and the content div within it
|
||||
const modalDialog = document.querySelector('div[role="dialog"][data-state="open"]');
|
||||
|
||||
if (modalDialog) {
|
||||
const contentDiv = modalDialog.querySelector('div.whitespace-pre-wrap');
|
||||
|
||||
if (contentDiv) {
|
||||
const content = contentDiv.textContent || contentDiv.innerText || '';
|
||||
|
||||
// Close the modal by clicking the close button
|
||||
const closeButton = modalDialog.querySelector('button.relative.can-focus svg');
|
||||
if (closeButton) {
|
||||
closeButton.closest('button').click();
|
||||
}
|
||||
|
||||
resolve(content);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
attempts++;
|
||||
if (attempts < maxAttempts) {
|
||||
setTimeout(handleModal, 100);
|
||||
} else {
|
||||
reject(new Error(`Modal with content not found for artifact: ${filename}`));
|
||||
}
|
||||
};
|
||||
|
||||
// Start checking for modal after a brief delay
|
||||
setTimeout(handleModal, 100);
|
||||
});
|
||||
},
|
||||
|
||||
async collectArtifacts() {
|
||||
// TODO: Implement project page artifact collection
|
||||
console.log('Project page artifact collection not yet implemented');
|
||||
return { artifacts: {}, fileMap: null };
|
||||
const artifactCollection = {};
|
||||
let fileMap = null;
|
||||
|
||||
const artifactList = this.getArtifactListItems();
|
||||
|
||||
if (Object.keys(artifactList).length === 0) {
|
||||
console.log('Nada');
|
||||
return { artifacts: artifactCollection, fileMap: fileMap };
|
||||
}
|
||||
|
||||
console.log(`Found ${Object.keys(artifactList).length} artifacts to collect`);
|
||||
|
||||
for (const [filename, isSelected] of Object.entries(artifactList)) {
|
||||
try {
|
||||
const content = await this.getArtifact(filename, isSelected);
|
||||
|
||||
if (filename === 'files.txt') {
|
||||
fileMap = content;
|
||||
console.log(`✓ Found files.txt - storing in fileMap`);
|
||||
} else {
|
||||
artifactCollection[filename] = content;
|
||||
console.log(`✓ Collected: ${filename}`);
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(`✗ Failed to collect: ${filename} - ${error.message}`);
|
||||
}
|
||||
|
||||
await new Promise(resolve => setTimeout(resolve, 500));
|
||||
}
|
||||
|
||||
return { artifacts: artifactCollection, fileMap: fileMap };
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
const ArtifactScraper = {
|
||||
|
||||
async collectArtifacts() {
|
||||
console.log('Collecting')
|
||||
if (ProjectMeta.isProjectChat()) {
|
||||
console.log('Detected project chat - using ChatArtifactScraper');
|
||||
return await ChatArtifactScraper.collectArtifacts();
|
||||
|
||||
Reference in New Issue
Block a user