Monitors UK TCG shops every 10 minutes and sends Discord + email alerts the moment a product flips from sold out / coming soon to available or pre-order.
| Shop | Method |
|---|---|
| Total Cards | Shopify JSON API |
| Hammerhead TCG | Shopify JSON API |
| Magic Madhouse | HTML scraper |
| Zatu Games | HTML scraper |
| Wayland Games | HTML scraper |
Any other shop can be added to products.json — the HTML scraper works generically.
git clone https://github.com/YOUR_USERNAME/YOUR_REPO.git
cd YOUR_REPO
pip install -r requirements.txtcp .env.example .envOpen .env and fill in:
| Variable | Where to get it |
|---|---|
DISCORD_WEBHOOK_URL |
Discord server → Server Settings → Integrations → Webhooks → New Webhook |
EMAIL_FROM |
Your Gmail address |
EMAIL_TO |
Destination address (can be the same) |
EMAIL_APP_PASSWORD |
Google App Passwords — requires 2FA enabled; not your normal password |
Edit products.json:
[
{
"url": "https://totalcards.net/collections/one-piece-pre-orders/products/...",
"name": "OP-16 Booster Box (Total Cards)"
},
{
"url": "https://zatugames.co.uk/products/...",
"name": "OP-16 Booster Box (Zatu)"
}
]The name field is optional — if omitted the script reads the product title from the page.
python monitor.pyOn first run the script records a baseline and sends no alerts. On every subsequent run it alerts if the status changed.
The workflow runs every 10 minutes using GitHub's free Actions minutes.
git init
git add .
git commit -m "init"
git remote add origin https://github.com/YOUR_USERNAME/YOUR_REPO.git
git push -u origin mainGo to Settings → Secrets and variables → Actions → New repository secret and add:
| Secret name | Value |
|---|---|
DISCORD_WEBHOOK_URL |
Your webhook URL |
EMAIL_FROM |
Your Gmail address |
EMAIL_TO |
Recipient address |
EMAIL_APP_PASSWORD |
Your Gmail App Password |
If you only want Discord alerts and not email (or vice versa), just leave the unused secrets empty — the script skips whichever service isn't configured.
GitHub Actions is enabled by default on new repos. The workflow runs automatically via the schedule, or you can trigger it manually from the Actions tab → Run workflow.
status.json is committed back to the repo after each run so state persists between runs.
- Reads
products.jsonfor URLs to check. - For Shopify shops, calls the
/products/{handle}.jsonendpoint — fast and accurate. - For other shops, fetches the HTML page and scans buttons, availability labels, and badges for keywords.
- Compares the detected status against
status.jsonfrom the previous run. - If the status changed, sends a Discord embed and/or email.
- Writes the updated status back to
status.json.
| Status | Meaning |
|---|---|
available |
Add to cart / buy now |
preorder |
Pre-order / available to pre-order |
sold_out |
Sold out / out of stock / coming soon |
unknown |
Could not determine — check the URL manually |
No alerts on first run — this is intentional. The first run saves a baseline. Alerts fire on the next run if anything changed.
unknown status — the scraper couldn't find a clear signal. Open the URL in your browser and check whether the shop uses heavy JavaScript to render the add-to-cart button (common with some Magento shops). You may need to add a site-specific selector in fetch_html().
Gmail "Login denied" — make sure you're using an App Password, not your regular Gmail password, and that 2FA is enabled on your Google account.