Skill: jgramajo4/camelcamelcamel-alerts (version 1.0.0)

--- name: camelcamelcamel-alerts description: Monitor CamelCamelCamel price drop alerts via RSS and send Telegram notifications when items go on sale. Use when setting up automatic price tracking for Amazon products with CamelCamelCamel price alerts. --- # CamelCamelCamel Alerts Automatically monitor your CamelCamelCamel RSS feed for Amazon price drops and get notified on Telegram. ## Quick Start 1. **Get your RSS feed URL** from CamelCamelCamel: - Go to https://camelcamelcamel.com/ and set up price alerts - Get your personal RSS feed URL (format: `https://camelcamelcamel.com/alerts/YOUR_UNIQUE_ID.xml`) 2. **Create a cron job** with YOUR feed URL (not someone else's!): ```bash cron add \ --job '{ "name": "camelcamelcamel-monitor", "schedule": "0 */12 * * *", "task": "Monitor CamelCamelCamel price alerts", "command": "python3 /path/to/scripts/fetch_rss.py https://camelcamelcamel.com/alerts/YOUR_UNIQUE_ID.xml" }' ``` **Important**: Replace `YOUR_UNIQUE_ID` with your own feed ID from step 1. Each person needs their own feed URL! 3. **Clawdbot will**: - Fetch your feed every 4 hours - Detect new price alerts - Send you Telegram notifications ## How It Works The skill uses two components: ### `scripts/fetch_rss.py` - Fetches your CamelCamelCamel RSS feed - Parses price alert items - Compares against local cache to find new alerts - Outputs JSON with new items detected - Caches item hashes to avoid duplicate notifications ### Cron Integration - Runs on a schedule you define - Triggers fetch_rss.py - Can be configured to run hourly, every 4 hours, daily, etc. ## Setup & Configuration **See [SETUP.md](references/SETUP.md)** for: - How to get your CamelCamelCamel RSS feed URL - Step-by-step cron configuration - Customizing check frequency - Cache management - Troubleshooting ## Alert Cache The script maintains a cache at `/tmp/camelcamelcamel/cache.json` to track which alerts have been notified. This prevents duplicate notifications. **Clear the cache** to re-test notifications: ```bash rm /tmp/camelcamelcamel/cache.json ``` ## Notification Format When a new price drop is detected, you'll receive a Telegram message like: ``` 🛒 *Price Alert* *PRODUCT NAME - $XX.XX (Down from $YY.YY)* Current price: $XX.XX Historical low: $ZZ.ZZ Last checked: [timestamp] View on Amazon: [link] ``` ## Customization ### Check Frequency Adjust the cron schedule (6th parameter in the `schedule` field): - `0 * * * *` → every hour - `0 */4 * * *` → every 4 hours (default) - `0 */6 * * *` → every 6 hours - `0 0 * * *` → daily ### Message Format Edit `scripts/notify.sh` to customize the Telegram message layout and emoji. ## Technical Details - **Language**: Python 3 (built-in libraries only) - **Cache**: JSON file at `/tmp/camelcamelcamel/cache.json` - **Feed Format**: Standard RSS/XML - **Dependencies**: None beyond Python standard library - **Timeout**: 10 seconds per feed fetch ## Troubleshooting If you're not receiving notifications: 1. **Verify the feed URL** works in your browser 2. **Check the cron job** exists: `cron list` 3. **Test manually**: ```bash python3 scripts/fetch_rss.py <YOUR_FEED_URL> /tmp/camelcamelcamel ``` 4. **Clear the cache** to reset: ```bash rm /tmp/camelcamelcamel/cache.json ``` 5. **Check Telegram** is configured in Clawdbot See [SETUP.md](references/SETUP.md) for more details.

path: references/SETUP.md
content: # CamelCamelCamel Alerts Setup Guide

## Overview

This skill monitors **your personal** CamelCamelCamel RSS feed for Amazon price drops and sends you Telegram notifications.

⚠️ **Important**: Each user must use their own CamelCamelCamel feed URL. Do not share or reuse someone else's feed URL—you'll only see alerts for their watchlist.

## Prerequisites

- CamelCamelCamel RSS feed URL (e.g., `https://camelcamelcamel.com/alerts/YOUR_FEED_ID.xml`)
- Telegram setup (Clawdbot must have Telegram configured)
- Python 3 with urllib (built-in)

## Setup Steps

### 1. Retrieve Your CamelCamelCamel Feed URL

1. Go to [CamelCamelCamel](https://camelcamelcamel.com/)
2. Create alerts for products you want to track
3. Copy your personal RSS feed URL from the alerts page

Example format:
```
https://camelcamelcamel.com/alerts/46b7418010d2395d2f6fcea824e4ae18c699cfd3.xml
```

### 2. Configure Clawdbot to Check the Feed

Add a cron job to check the feed periodically (recommend every 1-6 hours):

```bash
cron --action add \
  --job '{
    "name": "camelcamelcamel-check",
    "schedule": "0 */4 * * *",
    "task": "Check CamelCamelCamel price alerts",
    "command": "python3 /home/goliso/clawd/skills/camelcamelcamel-alerts/scripts/fetch_rss.py <YOUR_FEED_URL> /tmp/camelcamelcamel | jq '.alerts' | /home/goliso/clawd/skills/camelcamelcamel-alerts/scripts/notify.sh"
  }'
```

Replace `<YOUR_FEED_URL>` with your actual feed URL.

### 3. Cache Directory

The script stores a cache at `/tmp/camelcamelcamel/cache.json` to track which alerts have been seen.

Clear the cache if you want to re-trigger notifications for existing alerts:
```bash
rm /tmp/camelcamelcamel/cache.json
```

## How It Works

1. **Fetch**: Downloads your RSS feed
2. **Parse**: Extracts price alert items
3. **Compare**: Checks against cache to identify new/updated items
4. **Notify**: Sends Telegram message for each new alert
5. **Cache**: Stores item hashes to avoid duplicate notifications

## RSS Feed Format

CamelCamelCamel RSS includes:
- **title**: Product name + price info
- **link**: Direct link to Amazon product
- **description**: Price details and historical context
- **pubDate**: When the alert was generated

## Customization

### Check Frequency

Adjust the cron schedule (6th field in cron expression):
- `0 */4 * * *` → every 4 hours
- `0 */1 * * *` → every hour
- `0 */6 * * *` → every 6 hours

### Notification Format

Edit the notification script to customize the Telegram message format.

## Troubleshooting

**No notifications:**
- Check that the feed URL is valid (test in browser)
- Verify cron job is running: `cron --action list`
- Check `/tmp/camelcamelcamel/cache.json` exists
- Clear cache to re-trigger alerts

**Duplicate notifications:**
- Cache file may have been corrupted; delete and restart

**Feed fetch errors:**
- Test the URL directly: `curl https://camelcamelcamel.com/alerts/YOUR_ID.xml`
- Ensure internet connectivity


path: scripts/fetch_rss.py
content: #!/usr/bin/env python3
"""
Fetch and parse CamelCamelCamel RSS alerts.
Compares against cache to detect new/updated items.
"""

import os
import sys
import json
import xml.etree.ElementTree as ET
from urllib.request import urlopen
from urllib.error import URLError
from datetime import datetime
from pathlib import Path

def load_cache(cache_file):
    """Load cached item hashes."""
    if os.path.exists(cache_file):
        with open(cache_file, 'r') as f:
            return json.load(f)
    return {}

def save_cache(cache_file, cache_data):
    """Save item hashes to cache."""
    os.makedirs(os.path.dirname(cache_file), exist_ok=True)
    with open(cache_file, 'w') as f:
        json.dump(cache_data, f, indent=2)

def fetch_rss(feed_url):
    """Fetch RSS feed from URL."""
    try:
        with urlopen(feed_url, timeout=10) as response:
            return response.read().decode('utf-8')
    except URLError as e:
        print(f"Error fetching feed: {e}", file=sys.stderr)
        return None

def parse_rss(xml_content):
    """Parse RSS XML and extract alert items."""
    try:
        root = ET.fromstring(xml_content)
        items = []
        
        # CamelCamelCamel RSS structure
        for item in root.findall('.//item'):
            title_elem = item.find('title')
            link_elem = item.find('link')
            desc_elem = item.find('description')
            pubdate_elem = item.find('pubDate')
            
            if title_elem is not None:
                item_data = {
                    'title': title_elem.text or '',
                    'link': link_elem.text if link_elem is not None else '',
                    'description': desc_elem.text if desc_elem is not None else '',
                    'pubDate': pubdate_elem.text if pubdate_elem is not None else '',
                }
                items.append(item_data)
        
        return items
    except ET.ParseError as e:
        print(f"Error parsing RSS: {e}", file=sys.stderr)
        return []

def extract_price_info(description):
    """Extract current price and drop info from description."""
    # CamelCamelCamel descriptions typically contain: current price, historical low, etc.
    # Return parsed info or raw description if parsing fails
    return description

def main():
    if len(sys.argv) < 2:
        print("Usage: fetch_rss.py <feed_url> [cache_dir]")
        sys.exit(1)
    
    feed_url = sys.argv[1]
    cache_dir = sys.argv[2] if len(sys.argv) > 2 else "/tmp/camelcamelcamel"
    cache_file = os.path.join(cache_dir, "cache.json")
    
    # Fetch feed
    xml_content = fetch_rss(feed_url)
    if not xml_content:
        sys.exit(1)
    
    # Parse items
    items = parse_rss(xml_content)
    if not items:
        print("No items found in feed")
        sys.exit(0)
    
    # Load cache
    cache = load_cache(cache_file)
    
    # Detect new/updated items
    new_alerts = []
    for item in items:
        # Create simple hash of title + description
        item_key = f"{item['title']}|{item['description'][:100]}"
        item_hash = hash(item_key) % (2**31)  # Keep it reasonable
        
        if str(item_hash) not in cache:
            new_alerts.append({
                'hash': item_hash,
                'title': item['title'],
                'link': item['link'],
                'description': item['description'],
                'pubDate': item['pubDate'],
                'detected_at': datetime.utcnow().isoformat()
            })
            cache[str(item_hash)] = item['pubDate']
    
    # Save updated cache
    save_cache(cache_file, cache)
    
    # Output new alerts as JSON (for processing by cron/notification handler)
    if new_alerts:
        output = {
            'timestamp': datetime.utcnow().isoformat(),
            'alerts': new_alerts,
            'count': len(new_alerts)
        }
        print(json.dumps(output, indent=2))
    else:
        print(json.dumps({'timestamp': datetime.utcnow().isoformat(), 'alerts': [], 'count': 0}))

if __name__ == '__main__':
    main()


path: scripts/notify.sh
content: #!/bin/bash
# Send Telegram notifications for new CamelCamelCamel alerts
# Input: JSON array from fetch_rss.py on stdin

# Read JSON from stdin
json_input=$(cat)

# Check if we have alerts
alert_count=$(echo "$json_input" | jq 'length' 2>/dev/null)

if [[ -z "$alert_count" || "$alert_count" == "0" || "$alert_count" == "null" ]]; then
    exit 0
fi

# Process each alert
echo "$json_input" | jq -c '.[]' | while read -r alert; do
    title=$(echo "$alert" | jq -r '.title // "No title"')
    link=$(echo "$alert" | jq -r '.link // ""')
    description=$(echo "$alert" | jq -r '.description // "No details"' | head -c 200)
    
    # Format message
    message="🛒 *Price Alert*\n\n*${title}*\n\n${description}\n\n[View on Amazon](${link})"
    
    # Send via Clawdbot (using message tool)
    # This will be called from a parent process that has access to message tool
    # Output in format that can be piped to message action
    echo "ALERT|$title|$message|$link"
done


Security scan verdicts — ClawScan: clean | static analysis: clean | VirusTotal: clean | SkillSpector: clean (LOW)