diff --git a/.dockerignore b/.dockerignore index aa1e2e1..f5212a8 100644 --- a/.dockerignore +++ b/.dockerignore @@ -6,4 +6,6 @@ __pycache__ *.pyc *.md SECRETS.md -docker-compose.yml +docker-compose*.yml +LICENSE +test_*.py diff --git a/.env.example b/.env.example index ae7d36e..190a10f 100644 --- a/.env.example +++ b/.env.example @@ -1,19 +1,74 @@ -# Copy to .env and fill in. All values are required. +# ============================================================================= +# carousell-monitor — example environment file +# +# Copy to `.env` and fill in: +# cp .env.example .env +# +# `.env` is gitignored. NEVER commit real values. +# Every value below is read by docker compose (`${VAR}`) and passed into the +# container. Operational knobs (which searches to watch, how often) are NOT +# here — they live in NocoDB's `Settings` table, so you can change them from +# the web UI without a restart. +# ============================================================================= -# NocoDB (container DNS when on bridge_hoelee; LAN IP from a desktop): -NOCODB_URL=http://nocodb:10380 -NOCODB_BASE_ID=poqw1zjw3hnsk37 +# ---------------------------------------------------------------------------- +# NocoDB (the archive database) — REQUIRED +# ---------------------------------------------------------------------------- +# Where the monitor talks to NocoDB. +# all-in-one stack : http://nocodb:8080 (the compose service name) +# existing NocoDB : the container's name on the shared docker network +NOCODB_URL=http://nocodb:8080 + +# The base that holds the four tables. Open the base in NocoDB and copy the id +# out of the browser URL: +# http://:8080/dashboard/#/nc/base//... +NOCODB_BASE_ID= + +# NocoDB API token (starts with `nc_pat_`). Create it in NocoDB: +# avatar (bottom-left) -> Account Settings -> Tokens -> Create token +# You may leave it blank for the very first start — the monitor refuses to run +# with a clear error until it is set. NOCODB_TOKEN= -# Telegram alerts (@HoeleeAgentBot): +# ---------------------------------------------------------------------------- +# Telegram (where alerts are sent) — REQUIRED +# ---------------------------------------------------------------------------- +# 1. Talk to @BotFather in Telegram -> /newbot -> copy the token it gives you. +# 2. Get your numeric chat id from @userinfobot (send it any message). +# For a group: add the bot to the group, send a message, then read chat.id +# from https://api.telegram.org/bot/getUpdates TELEGRAM_BOT_TOKEN= -TELEGRAM_CHAT_ID=5648309582 +TELEGRAM_CHAT_ID= -# Optional tuning: +# ---------------------------------------------------------------------------- +# NocoDB container settings (all-in-one stack only) +# ---------------------------------------------------------------------------- +# Signing secret for NocoDB login sessions. Generate one: +# openssl rand -hex 32 +NC_AUTH_JWT_SECRET= + +# Host port for the NocoDB web UI -> container port 8080. +NOCODB_PORT=8080 + +# ---------------------------------------------------------------------------- +# Optional tuning (defaults are sane; leave blank to use the defaults) +# ---------------------------------------------------------------------------- +# How often the monitor wakes up (seconds). This is the heartbeat, not the +# per-search interval — that one is `check_interval_minutes` in NocoDB. TICK_SECONDS=60 + +# Minimum pause (seconds) between two Carousell requests inside one tick. +# Prevents a burst of requests when many searches come due at once. 0 disables. FETCH_GAP_SECONDS=1 -HEALTH_STALE_SECONDS=600 -# 连续失败几次才发 Telegram 故障告警(去抖): -ERROR_ALERT_AFTER=3 -# 失败 watch 占比达到该值才判定整轮故障(1.0 = 全部失败): + +# A tick that fails every watch marks the container unhealthy. One flaky +# search should not, so the tick is only "failed" when this fraction of the +# watches failed (1.0 = all of them must fail; 0 = never fail). FAILURE_RATIO_THRESHOLD=1.0 + +# Send the Telegram failure alert only after this many consecutive failed +# ticks, and one recovery notice when it clears (debounce, avoids spam). +ERROR_ALERT_AFTER=3 + +# Container clock. Timestamps written to NocoDB are UTC on purpose. +TZ=Asia/Kuala_Lumpur diff --git a/.gitignore b/.gitignore index 0a16c91..15161d8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,11 @@ .env +.env.local +SECRETS.md +OPS-INTERNAL.md __pycache__/ *.pyc +*.pyo .DS_Store +*.bak +*.bak[0-9] +_tmp_* diff --git a/AGENTS.md b/AGENTS.md index 1586e8d..5e7ad39 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,77 +1,105 @@ # AGENTS.md -Project: Carousell new-listing monitor (Python stdlib, Docker, NocoDB, Telegram). +Entry point for AI coding agents working on **carousell-monitor**: a Python-stdlib +monitor that polls Carousell search pages, archives every listing to NocoDB, and +alerts Telegram. + +Read this file, then the doc that matches your task. Keep it updated when the +layout or the deployment story changes. ## What it does -`monitor.py` polls Carousell search URLs (sort_by=3 = recent), extracts listings +`monitor.py` polls Carousell search URLs (`sort_by=3` = recent), extracts listings from the server-rendered `