Pokemon Stock Monitor - Initial commit
Chrome extension for PokemonCenter monitoring with Discord notifications. Includes Python scripts for Target monitoring. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,183 @@
|
||||
"""
|
||||
Discord webhook notifications for stock alerts
|
||||
Sends rich embeds with product info and direct links
|
||||
"""
|
||||
|
||||
import logging
|
||||
import requests
|
||||
from datetime import datetime
|
||||
from typing import Optional
|
||||
from config import DISCORD_WEBHOOK_URL
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# Colors for different notification types
|
||||
COLOR_RESTOCK = 0x00FF00 # Green - item back in stock
|
||||
COLOR_NEW_DROP = 0x0099FF # Blue - new product listing
|
||||
COLOR_PREORDER = 0xFFAA00 # Orange - pre-order available
|
||||
COLOR_ERROR = 0xFF0000 # Red - error notification
|
||||
|
||||
# Site icons/emojis
|
||||
SITE_EMOJIS = {
|
||||
"pokemoncenter": "\U0001F7E1", # Yellow circle
|
||||
"target": "\U0001F534", # Red circle
|
||||
"walmart": "\U0001F535", # Blue circle
|
||||
"bestbuy": "\U0001F7E1", # Yellow circle
|
||||
}
|
||||
|
||||
|
||||
def send_stock_alert(
|
||||
product_name: str,
|
||||
product_url: str,
|
||||
price: str,
|
||||
site: str,
|
||||
alert_type: str = "restock",
|
||||
image_url: Optional[str] = None,
|
||||
):
|
||||
"""
|
||||
Send a Discord notification for a stock alert
|
||||
|
||||
Args:
|
||||
product_name: Name of the product
|
||||
product_url: Direct link to the product
|
||||
price: Price string (e.g., "$49.99")
|
||||
site: Site name (pokemoncenter, target, etc.)
|
||||
alert_type: "restock", "new_drop", or "preorder"
|
||||
image_url: Optional product image URL
|
||||
"""
|
||||
if DISCORD_WEBHOOK_URL == "YOUR_WEBHOOK_URL_HERE":
|
||||
logger.error("Discord webhook URL not configured! Update config.py")
|
||||
return False
|
||||
|
||||
# Choose color based on alert type
|
||||
if alert_type == "restock":
|
||||
color = COLOR_RESTOCK
|
||||
title = f"\U0001F6A8 RESTOCK ALERT"
|
||||
elif alert_type == "new_drop":
|
||||
color = COLOR_NEW_DROP
|
||||
title = f"\U0001F195 NEW DROP"
|
||||
elif alert_type == "preorder":
|
||||
color = COLOR_PREORDER
|
||||
title = f"\u23F0 PRE-ORDER AVAILABLE"
|
||||
else:
|
||||
color = COLOR_RESTOCK
|
||||
title = f"\U0001F514 STOCK ALERT"
|
||||
|
||||
site_emoji = SITE_EMOJIS.get(site.lower(), "\U0001F6D2")
|
||||
site_display = site.replace("pokemoncenter", "Pokemon Center").title()
|
||||
|
||||
# Build the embed
|
||||
embed = {
|
||||
"title": title,
|
||||
"description": f"**{product_name}**",
|
||||
"url": product_url,
|
||||
"color": color,
|
||||
"fields": [
|
||||
{"name": "Price", "value": price or "See link", "inline": True},
|
||||
{"name": "Store", "value": f"{site_emoji} {site_display}", "inline": True},
|
||||
{"name": "Link", "value": f"[\U0001F6D2 BUY NOW]({product_url})", "inline": False},
|
||||
],
|
||||
"footer": {"text": "Pokemon Stock Monitor"},
|
||||
"timestamp": datetime.utcnow().isoformat(),
|
||||
}
|
||||
|
||||
if image_url:
|
||||
embed["thumbnail"] = {"url": image_url}
|
||||
|
||||
payload = {
|
||||
"content": "@everyone", # Ping everyone
|
||||
"embeds": [embed],
|
||||
}
|
||||
|
||||
try:
|
||||
response = requests.post(
|
||||
DISCORD_WEBHOOK_URL,
|
||||
json=payload,
|
||||
timeout=10,
|
||||
)
|
||||
response.raise_for_status()
|
||||
logger.info(f"Discord notification sent for: {product_name}")
|
||||
return True
|
||||
except requests.exceptions.RequestException as e:
|
||||
logger.error(f"Failed to send Discord notification: {e}")
|
||||
return False
|
||||
|
||||
|
||||
def send_error_notification(error_message: str, site: str = "Unknown"):
|
||||
"""Send an error notification to Discord"""
|
||||
if DISCORD_WEBHOOK_URL == "YOUR_WEBHOOK_URL_HERE":
|
||||
return False
|
||||
|
||||
embed = {
|
||||
"title": "\u26A0\uFE0F Monitor Error",
|
||||
"description": error_message,
|
||||
"color": COLOR_ERROR,
|
||||
"fields": [{"name": "Site", "value": site, "inline": True}],
|
||||
"footer": {"text": "Pokemon Stock Monitor"},
|
||||
"timestamp": datetime.utcnow().isoformat(),
|
||||
}
|
||||
|
||||
payload = {"embeds": [embed]}
|
||||
|
||||
try:
|
||||
response = requests.post(DISCORD_WEBHOOK_URL, json=payload, timeout=10)
|
||||
response.raise_for_status()
|
||||
return True
|
||||
except requests.exceptions.RequestException as e:
|
||||
logger.error(f"Failed to send error notification: {e}")
|
||||
return False
|
||||
|
||||
|
||||
def send_startup_notification():
|
||||
"""Send a notification that the monitor has started"""
|
||||
if DISCORD_WEBHOOK_URL == "YOUR_WEBHOOK_URL_HERE":
|
||||
return False
|
||||
|
||||
embed = {
|
||||
"title": "\u2705 Monitor Started",
|
||||
"description": "Pokemon Stock Monitor is now running and watching for restocks!",
|
||||
"color": 0x00FF00,
|
||||
"footer": {"text": "Pokemon Stock Monitor"},
|
||||
"timestamp": datetime.utcnow().isoformat(),
|
||||
}
|
||||
|
||||
payload = {"embeds": [embed]}
|
||||
|
||||
try:
|
||||
response = requests.post(DISCORD_WEBHOOK_URL, json=payload, timeout=10)
|
||||
response.raise_for_status()
|
||||
return True
|
||||
except requests.exceptions.RequestException as e:
|
||||
logger.error(f"Failed to send startup notification: {e}")
|
||||
return False
|
||||
|
||||
|
||||
def test_webhook():
|
||||
"""Test the Discord webhook connection"""
|
||||
print("Testing Discord webhook...")
|
||||
|
||||
if DISCORD_WEBHOOK_URL == "YOUR_WEBHOOK_URL_HERE":
|
||||
print("ERROR: Webhook URL not configured!")
|
||||
print("Edit config.py and set DISCORD_WEBHOOK_URL")
|
||||
return False
|
||||
|
||||
# Send a test notification
|
||||
success = send_stock_alert(
|
||||
product_name="Test Product - Pokemon TCG Booster",
|
||||
product_url="https://www.pokemoncenter.com/test",
|
||||
price="$4.99",
|
||||
site="pokemoncenter",
|
||||
alert_type="restock",
|
||||
)
|
||||
|
||||
if success:
|
||||
print("SUCCESS! Check your Discord channel for the test message.")
|
||||
else:
|
||||
print("FAILED! Check the webhook URL and try again.")
|
||||
|
||||
return success
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Run webhook test
|
||||
test_webhook()
|
||||
Reference in New Issue
Block a user