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 `
|
return `
|
||||||
<div class="activity-item">
|
<div class="activity-item">
|
||||||
${hasProductImage
|
${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
|
: storeLogoHtml
|
||||||
}
|
}
|
||||||
<div class="activity-details">
|
<div class="activity-details">
|
||||||
@@ -297,6 +297,19 @@ async function loadActivityFeed() {
|
|||||||
}).join('');
|
}).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
|
// Navigate to products filtered by event type
|
||||||
function goToFilteredProducts(eventType, period) {
|
function goToFilteredProducts(eventType, period) {
|
||||||
currentEventFilter = { type: eventType, period: period };
|
currentEventFilter = { type: eventType, period: period };
|
||||||
@@ -718,7 +731,7 @@ function cleanProductName(name) {
|
|||||||
.replace(/\{[^}]*\}/g, '') // Remove any remaining {css} blocks
|
.replace(/\{[^}]*\}/g, '') // Remove any remaining {css} blocks
|
||||||
.replace(/\d+\s*Reviews?$/i, '') // Remove trailing "X Reviews"
|
.replace(/\d+\s*Reviews?$/i, '') // Remove trailing "X Reviews"
|
||||||
// Fix Pokémon - multiple encoding patterns
|
// 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')
|
.replace(/Pokémon/gi, 'Pokémon')
|
||||||
.replace(/Pokテゥmon/gi, 'Pokémon')
|
.replace(/Pokテゥmon/gi, 'Pokémon')
|
||||||
|
|||||||
+282
-853
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 json
|
||||||
import logging
|
import logging
|
||||||
|
import re
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Dict, List, Set, Optional, Tuple
|
from typing import Dict, List, Set, Optional, Tuple
|
||||||
from dataclasses import asdict
|
from dataclasses import asdict
|
||||||
@@ -53,6 +54,12 @@ class ProductTracker:
|
|||||||
except IOError as e:
|
except IOError as e:
|
||||||
logger.error(f"Error saving products file: {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]]:
|
def process_products(self, products: List[Product]) -> Tuple[List[Product], List[Product]]:
|
||||||
"""
|
"""
|
||||||
Process a list of scraped products and detect changes.
|
Process a list of scraped products and detect changes.
|
||||||
@@ -68,7 +75,7 @@ class ProductTracker:
|
|||||||
restocked_products = []
|
restocked_products = []
|
||||||
|
|
||||||
for product in products:
|
for product in products:
|
||||||
url = product.url
|
url = self._normalize_url(product.url)
|
||||||
now = datetime.now().isoformat()
|
now = datetime.now().isoformat()
|
||||||
|
|
||||||
# Get or create product in database
|
# Get or create product in database
|
||||||
|
|||||||
Reference in New Issue
Block a user