Files
openclaw/tools/price-monitor.sh
Clawd Bot ca9b510922 chore: align with upstream openclaw/openclaw and overlay local additions
- Reset master to upstream/main (16,697 commits)
- Overlay 2,271 local-only files (skills, tools, workspace, configs, apps)
- Restore IDENTITY.md and USER.md templates
- Build verified, gateway running, Discord working

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 07:40:46 +01:00

211 lines
6.7 KiB
Bash

#!/usr/bin/env bash
# price-monitor.sh - Pris-overvagning for produkter (homeshop.dk + pricerunner.dk)
# Brug: bash price-monitor.sh <produkt-id>
# Eksempel: bash price-monitor.sh dewalt-dcd996nt
set -euo pipefail
PRODUCT_ID="${1:-dewalt-dcd996nt}"
DB_FILE="/home/alex/clawd/data/prices/${PRODUCT_ID}.json"
if [[ ! -f "$DB_FILE" ]]; then
echo "FEJL: Database ikke fundet: $DB_FILE" >&2
exit 1
fi
# Les konfiguration fra database
URL=$(python3 -c "import json,sys; d=json.load(open('$DB_FILE')); print(d['url'])")
BASELINE=$(python3 -c "import json,sys; d=json.load(open('$DB_FILE')); print(d['baseline_price'])")
THRESHOLD=$(python3 -c "import json,sys; d=json.load(open('$DB_FILE')); print(d['alert_threshold_pct'])")
BUY_UNDER=$(python3 -c "import json,sys; d=json.load(open('$DB_FILE')); print(d['buy_under_dkk'])")
PRODUCT=$(python3 -c "import json,sys; d=json.load(open('$DB_FILE')); print(d['product'])")
PR_SEARCH=$(python3 -c "import json,sys; d=json.load(open('$DB_FILE')); print(d.get('pricerunner_search', ''))")
echo "=== Pris-check: $PRODUCT ==="
echo "Baseline: ${BASELINE} DKK | Threshold: ${THRESHOLD}% | Kobsgraense: ${BUY_UNDER} DKK"
echo ""
# -------------------------------------------------------
# Funktion: Scrape homeshop.dk
# -------------------------------------------------------
scrape_homeshop() {
python3 /home/alex/clawd/tools/scrape-price.py "$URL" 2>/dev/null
}
# -------------------------------------------------------
# Funktion: Scrape pricerunner.dk sogeside
# -------------------------------------------------------
scrape_pricerunner() {
local search_url="$1"
if [[ -z "$search_url" ]]; then
echo "N/A"
return
fi
python3 /home/alex/clawd/tools/scrape-price.py "$search_url" 2>/dev/null
}
# -------------------------------------------------------
# Hent priser fra begge kilder
# -------------------------------------------------------
echo "Henter pris fra homeshop.dk..."
HOMESHOP_PRICE=$(scrape_homeshop)
echo "Henter pris fra pricerunner.dk..."
PR_PRICE=$(scrape_pricerunner "$PR_SEARCH")
# -------------------------------------------------------
# Find laveste pris
# -------------------------------------------------------
BEST_SOURCE="homeshop.dk"
BEST_PRICE_RAW="$HOMESHOP_PRICE"
if [[ "$HOMESHOP_PRICE" == "ERROR" || -z "$HOMESHOP_PRICE" ]]; then
echo "ADVARSEL: Kunne ikke hente pris fra homeshop.dk" >&2
HOMESHOP_PRICE="N/A"
fi
CURRENT_INT=""
if [[ "$HOMESHOP_PRICE" != "N/A" && "$HOMESHOP_PRICE" != "ERROR" ]]; then
CURRENT_INT=$(python3 -c "print(int(float('$HOMESHOP_PRICE')))" 2>/dev/null || echo "")
fi
# Sammenlign med PriceRunner hvis tilgaengelig
PR_INT=""
if [[ "$PR_PRICE" != "N/A" && -n "$PR_PRICE" ]]; then
PR_INT=$(python3 -c "print(int(float('$PR_PRICE')))" 2>/dev/null || echo "")
fi
# Vaelg laveste pris som "best"
if [[ -n "$PR_INT" && -n "$CURRENT_INT" ]]; then
BEST=$(python3 -c "
hs = $CURRENT_INT
pr = $PR_INT
if pr < hs:
print(f'pr:{pr}')
else:
print(f'hs:{hs}')
")
if [[ "$BEST" == pr:* ]]; then
BEST_SOURCE="pricerunner.dk"
BEST_PRICE_RAW="$PR_INT"
CURRENT_INT="$PR_INT"
fi
elif [[ -n "$PR_INT" && -z "$CURRENT_INT" ]]; then
BEST_SOURCE="pricerunner.dk"
CURRENT_INT="$PR_INT"
fi
echo ""
echo "--- Priser ---"
[[ "$HOMESHOP_PRICE" != "N/A" && "$HOMESHOP_PRICE" != "ERROR" ]] && \
echo " homeshop.dk: ${HOMESHOP_PRICE%.*} DKK"
[[ -n "$PR_INT" ]] && echo " pricerunner.dk: ${PR_INT} DKK (laveste fundet)"
[[ -z "$PR_INT" ]] && echo " pricerunner.dk: ikke tilgaengelig"
echo ""
if [[ -z "$CURRENT_INT" ]]; then
echo "FEJL: Ingen priser kunne hentes fra nogen kilde" >&2
exit 1
fi
echo "Bedste pris: ${CURRENT_INT} DKK (fra ${BEST_SOURCE})"
# Beregn aendring fra baseline
PRICE_CHANGE=$(python3 -c "
baseline = float($BASELINE)
current = float($CURRENT_INT)
pct = ((baseline - current) / baseline) * 100
print(f'{pct:.1f}')
")
echo "Aendring fra baseline (${BASELINE} DKK): ${PRICE_CHANGE}%"
TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
# -------------------------------------------------------
# Gem priser i database
# -------------------------------------------------------
python3 -c "
import json
db_file = '$DB_FILE'
with open(db_file, 'r') as f:
data = json.load(f)
entries = []
if '$HOMESHOP_PRICE' not in ('N/A', 'ERROR', ''):
entries.append({
'price': int(float('$HOMESHOP_PRICE')),
'currency': 'DKK',
'timestamp': '$TIMESTAMP',
'source': 'homeshop.dk'
})
if '$PR_INT' not in ('', 'N/A'):
entries.append({
'price': int('$PR_INT'),
'currency': 'DKK',
'timestamp': '$TIMESTAMP',
'source': 'pricerunner.dk'
})
data['prices'].extend(entries)
# Hold kun de 90 seneste priser
if len(data['prices']) > 90:
data['prices'] = data['prices'][-90:]
data['last_best_price'] = $CURRENT_INT
data['last_best_source'] = '$BEST_SOURCE'
data['last_checked'] = '$TIMESTAMP'
with open(db_file, 'w') as f:
json.dump(data, f, indent=2, ensure_ascii=False)
print(f'Priser gemt ({len(entries)} poster).')
"
# -------------------------------------------------------
# Alert-logik: baseret pa bedste pris
# -------------------------------------------------------
BELOW_BUY_UNDER=$(python3 -c "print('yes' if $CURRENT_INT <= $BUY_UNDER else 'no')")
TRIGGER_ALERT=$(python3 -c "
baseline = float($BASELINE)
current = float($CURRENT_INT)
threshold = float($THRESHOLD)
pct_drop = ((baseline - current) / baseline) * 100
print('yes' if pct_drop >= threshold else 'no')
")
echo ""
if [[ "$TRIGGER_ALERT" == "yes" ]]; then
PCT_DROP=$(python3 -c "
baseline = float($BASELINE)
current = float($CURRENT_INT)
pct = ((baseline - current) / baseline) * 100
print(f'{pct:.0f}')
")
echo "ALERT: Pris faldet >=${THRESHOLD}% fra baseline!"
PR_LINE=""
[[ -n "$PR_INT" ]] && PR_LINE="
PriceRunner: ${PR_INT} DKK"
ALERT_MSG="Prisfald! ${PRODUCT}: ${CURRENT_INT} DKK (var ${BASELINE} DKK, -${PCT_DROP}%) [${BEST_SOURCE}]${PR_LINE}
${URL}"
echo "Sender Discord alert..."
openclaw message send --channel discord --target "1466863360099356763" \
-m "$ALERT_MSG" 2>/dev/null || echo "ADVARSEL: Discord alert fejlede"
elif [[ "$BELOW_BUY_UNDER" == "yes" && "$CURRENT_INT" -lt "$BASELINE" ]]; then
echo "INFO: Pris under kobsgraense (${CURRENT_INT} <= ${BUY_UNDER} DKK)"
PR_LINE=""
[[ -n "$PR_INT" ]] && PR_LINE="
PriceRunner: ${PR_INT} DKK"
ALERT_MSG="KOB NU! ${PRODUCT}: ${CURRENT_INT} DKK (under kobsgraensen ${BUY_UNDER} DKK!) [${BEST_SOURCE}]${PR_LINE}
${URL}"
echo "Sender Discord alert (kobsgraense)..."
openclaw message send --channel discord --target "1466863360099356763" \
-m "$ALERT_MSG" 2>/dev/null || echo "ADVARSEL: Discord alert fejlede"
else
echo "OK: Ingen alert - bedste pris stabil (${CURRENT_INT} DKK, aendring: ${PRICE_CHANGE}%)"
fi
echo ""
echo "Pris-check fuldfert: $(date)"