// Pokemon Stock Monitor - Content Script // Runs on PokemonCenter pages to extract product data (function() { console.log("[Pokemon Monitor] Content script loaded on:", window.location.href); // Listen for messages from background script chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { if (message.type === "extractProducts") { console.log("[Pokemon Monitor] Extracting products..."); debugPageContent(); const products = extractProducts(); console.log("[Pokemon Monitor] Found", products.length, "products"); sendResponse(products); } return true; }); // Debug function to see what's on the page function debugPageContent() { console.log("[Pokemon Monitor] === PAGE DEBUG ==="); console.log("[Pokemon Monitor] Title:", document.title); console.log("[Pokemon Monitor] Body text length:", document.body?.textContent?.length || 0); // Check for bot protection indicators const bodyText = document.body?.textContent?.toLowerCase() || ""; if (bodyText.includes("verify") || bodyText.includes("robot") || bodyText.includes("captcha")) { console.log("[Pokemon Monitor] WARNING: Possible bot protection detected!"); } // Count all links const allLinks = document.querySelectorAll('a'); console.log("[Pokemon Monitor] Total links on page:", allLinks.length); // Check for product links with various patterns const productLinks = document.querySelectorAll('a[href*="/product/"]'); console.log("[Pokemon Monitor] Links with /product/:", productLinks.length); // Try alternative selectors const cardLinks = document.querySelectorAll('[class*="product"] a, [class*="card"] a, [class*="tile"] a'); console.log("[Pokemon Monitor] Links in product/card/tile containers:", cardLinks.length); // Sample some hrefs to understand page structure const sampleHrefs = Array.from(allLinks).slice(0, 10).map(a => a.href); console.log("[Pokemon Monitor] Sample hrefs:", sampleHrefs); // Look for any elements that might be products const possibleProducts = document.querySelectorAll('[class*="product"], [class*="card"], [data-product], [data-item]'); console.log("[Pokemon Monitor] Elements with product/card classes:", possibleProducts.length); console.log("[Pokemon Monitor] === END DEBUG ==="); } function extractProducts() { const products = []; // Group all product links by URL const urlToLinks = {}; document.querySelectorAll('a[href*="/product/"]').forEach(link => { const url = link.href; if (!urlToLinks[url]) { urlToLinks[url] = []; } urlToLinks[url].push(link); }); console.log("[Pokemon Monitor] Found", Object.keys(urlToLinks).length, "unique product URLs"); // Process each unique product URL for (const [url, links] of Object.entries(urlToLinks)) { // Find the best name from all links to this product let bestName = ""; let isSoldOut = false; for (const link of links) { const text = link.textContent.trim(); // Check if any link says "SOLD OUT" if (text.toUpperCase().includes("SOLD OUT")) { isSoldOut = true; } // Pick the longest non-"SOLD OUT" text as the name if (text.length > bestName.length && !text.toUpperCase().startsWith("SOLD") && text.length > 10) { bestName = text; } } // Skip if we couldn't find a good name if (!bestName || bestName.length < 10) continue; // Clean up name - remove price if embedded bestName = bestName.replace(/\$[\d,.]+/g, "").trim(); // Remove "Add to Cart" etc bestName = bestName.replace(/Add to Cart/gi, "").trim(); // Clean whitespace bestName = bestName.replace(/\s+/g, " ").trim(); // Find price from any of the links' containers let price = null; for (const link of links) { let parent = link.parentElement; for (let i = 0; i < 6 && parent && !price; i++) { const priceMatch = parent.textContent.match(/\$[\d,]+\.?\d*/); if (priceMatch) { price = priceMatch[0]; break; } parent = parent.parentElement; } if (price) break; } // Find image from any of the links let imageUrl = null; for (const link of links) { const img = link.querySelector("img") || link.closest("[class*='product']")?.querySelector("img"); if (img) { imageUrl = img.src || img.dataset.src; if (imageUrl && !imageUrl.startsWith("data:")) break; } } // Extract product ID from URL const idMatch = url.match(/\/product\/([^\/]+)/); const productId = idMatch ? idMatch[1] : url; products.push({ name: bestName, url: url, price: price, inStock: !isSoldOut, imageUrl: imageUrl, productId: productId, site: "pokemoncenter" }); } console.log("[Pokemon Monitor] Extracted products:", products.map(p => ({name: p.name.slice(0,40), inStock: p.inStock}))); return products; } })();