diff --git a/dashboard/static/app.js b/dashboard/static/app.js index a1be244..536ea98 100644 --- a/dashboard/static/app.js +++ b/dashboard/static/app.js @@ -281,7 +281,7 @@ async function loadActivityFeed() { return `
${hasProductImage - ? `` + ? `` : storeLogoHtml }
@@ -297,6 +297,19 @@ async function loadActivityFeed() { }).join(''); } +function handleActivityImageError(img, site) { + const storeInfo = STORE_INFO[site] || { name: site, color: '#333', bgColor: '#666', logo: '', fallback: '?' }; + const div = document.createElement('div'); + div.className = 'activity-store-icon'; + div.style.background = storeInfo.bgColor; + div.innerHTML = ` + + + `; + img.replaceWith(div); +} + // Navigate to products filtered by event type function goToFilteredProducts(eventType, period) { currentEventFilter = { type: eventType, period: period }; @@ -718,7 +731,7 @@ function cleanProductName(name) { .replace(/\{[^}]*\}/g, '') // Remove any remaining {css} blocks .replace(/\d+\s*Reviews?$/i, '') // Remove trailing "X Reviews" // Fix Pokémon - multiple encoding patterns - .replace(/Pok[éÃ\u00c3\u00a9]+mon/gi, 'Pokémon') + .replace(/Pok[éÃ\u00c3\u00a9\ufffd]+mon/gi, 'Pokémon') .replace(/Pokémon/gi, 'Pokémon') .replace(/Pokémon/gi, 'Pokémon') .replace(/Pokテゥmon/gi, 'Pokémon') diff --git a/debug_bestbuy.html b/debug_bestbuy.html index 816ad78..c9fe036 100644 --- a/debug_bestbuy.html +++ b/debug_bestbuy.html @@ -1,855 +1,41 @@ -pokemon trading cards - Best Buy
- + + + + + + + - - - - - - - - - -
Skip to contentGo to Product Search
Gift Ideas
- - -
- -
-
Main Content

pokemon trading cards

(483)
Sort by:
1-18 of 483 items
Tell us about your search experience
Sponsored
Sponsored
Sponsored

Similar products from outside of Best Buy

sponsored
- + + + + + + - - - - - - - - + - - -

\ No newline at end of file + + + + + + + + + + + + +

Early Black Friday DealsNew Doorbusters every Friday.Shop now

Skip to content
Gift Ideas
+ +
+
Main Content
+ +
+ +
Error symbol

We’re sorry, something went wrong.

You can use our search bar or pick a category below. If you typed in a URL, check it for errors.

+ +
+ + + +
+ +
+
+
+
+ + + +
+ + + + +
\ No newline at end of file diff --git a/src/product_tracker.py b/src/product_tracker.py index cf5989b..b010286 100644 --- a/src/product_tracker.py +++ b/src/product_tracker.py @@ -5,6 +5,7 @@ Now integrates with SQLite database for historical tracking. import json import logging +import re from pathlib import Path from typing import Dict, List, Set, Optional, Tuple from dataclasses import asdict @@ -53,6 +54,12 @@ class ProductTracker: except IOError as e: logger.error(f"Error saving products file: {e}") + def _normalize_url(self, url: str) -> str: + """Normalize product URL to avoid tracking the same product under different URLs""" + # Best Buy: strip /sku/XXXXX variant suffix — same product, different SKU variants + url = re.sub(r'/sku/\d+$', '', url) + return url.rstrip('/') + def process_products(self, products: List[Product]) -> Tuple[List[Product], List[Product]]: """ Process a list of scraped products and detect changes. @@ -68,7 +75,7 @@ class ProductTracker: restocked_products = [] for product in products: - url = product.url + url = self._normalize_url(product.url) now = datetime.now().isoformat() # Get or create product in database