Refactor activity image error handling and clean up debug_bestbuy
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+15
-2
@@ -281,7 +281,7 @@ async function loadActivityFeed() {
|
||||
return `
|
||||
<div class="activity-item">
|
||||
${hasProductImage
|
||||
? `<img src="${event.image_url}" class="activity-thumb" alt="" onerror="this.outerHTML=\`${storeLogoHtml.replace(/`/g, '\\`').replace(/\n/g, '')}\`">`
|
||||
? `<img src="${event.image_url}" class="activity-thumb" alt="" onerror="handleActivityImageError(this, '${event.site}')">`
|
||||
: storeLogoHtml
|
||||
}
|
||||
<div class="activity-details">
|
||||
@@ -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 src="${storeInfo.logo}" alt="${storeInfo.name}" class="activity-store-logo"
|
||||
onerror="this.style.display='none'; this.nextElementSibling.style.display='block';">
|
||||
<span class="activity-store-fallback" style="display:none; color:${storeInfo.color};">${storeInfo.fallback}</span>
|
||||
`;
|
||||
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')
|
||||
|
||||
+297
-868
File diff suppressed because one or more lines are too long
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user