Configurable monitoring and alerting engine for domain-specific signals.
Project description
SignalWatch
SignalWatch is a configurable product monitoring bot. It fetches product listings from external sources, normalises them into domain objects, stores seen items in SQLite, detects newly observed items, applies matching rules, and sends notifications.
The first production source is TK Maxx Gold Label.
Features
- Fetches TK Maxx Gold Label product listings with Playwright-rendered HTML.
- Normalises source-specific product cards into a shared
WatchItemdomain model. - Persists seen items in SQLite with
first_seen_atandlast_seen_attimestamps. - Detects new items across runs.
- Filters notifications by brand with case-insensitive matching.
- Supports log and Telegram notification adapters.
- Provides one-shot checks and long-running watch mode.
- Adds random polling jitter to avoid fixed, machine-like request intervals.
Architecture
SignalWatch keeps the monitoring pipeline layered:
CLI -> app workflow -> source -> WatchItem -> storage/dedup -> matching -> notification
Key modules:
signalwatch.cli: command-line entry point.signalwatch.app.run_bot: one monitoring cycle.signalwatch.app.watch: repeated monitoring loop with polling jitter.signalwatch.sources: external source adapters.signalwatch.storage: persistence adapters.signalwatch.matching: relevance filters such as brand matching.signalwatch.notify: notification interfaces and adapters.signalwatch.models: domain models shared across the pipeline.
The source layer only fetches and normalises products. Storage, deduplication, matching, scheduling, and notifications are kept outside source adapters.
Installation
SignalWatch requires Python 3.12 or newer.
python3 -m pip install -e ".[dev]"
python3 -m playwright install webkit
Configuration
Example Telegram configuration:
source:
type: tkmaxx
url: "https://www.tkmaxx.com/uk/en/mens-gold-label/c/02090000?sort=published_date+desc"
storage:
sqlite_path: "../data/tkmaxx.sqlite3"
notification:
type: telegram
bot_token_env: "SIGNALWATCH_TELEGRAM_BOT_TOKEN"
chat_id_env: "SIGNALWATCH_TELEGRAM_CHAT_ID"
matching:
brands:
- Balenciaga
- Rick Owens
- Palm Angels
- Off-White
- Saint Laurent
- Stone Island
- Givenchy
polling:
interval_seconds: 3600
jitter_seconds: 600
Relative paths such as storage.sqlite_path are resolved relative to the YAML
file location.
Usage
Run one monitoring cycle:
signalwatch check examples/tkmaxx-telegram.yml
Run continuously:
signalwatch watch examples/tkmaxx-telegram.yml
Stop watch mode with Ctrl+C.
Telegram Setup
- Create a bot with
@BotFather. - Send
/startto the bot. - Fetch updates to find your chat ID:
curl "https://api.telegram.org/bot<TOKEN>/getUpdates"
- Export the required environment variables:
export SIGNALWATCH_TELEGRAM_BOT_TOKEN="<TOKEN>"
export SIGNALWATCH_TELEGRAM_CHAT_ID="<CHAT_ID>"
- Run:
signalwatch check examples/tkmaxx-telegram.yml
Telegram messages use a compact HTML-formatted layout:
❗ NEW ITEM
Gucci & Co - Leather belt
💷 £199.99 | RRP £410.00 | Save £210.01 (51%)
⚠️ ONLY 1 LEFT
https://example.com/products/1
Matching
Brand matching is case-insensitive:
matching:
brands:
- Balenciaga
- Rick Owens
The following source values all match Balenciaga:
Balenciaga
BALENCIAGA
balenciaga
If matching is omitted or matching.brands is empty, all newly seen items are
eligible for notification.
Storage still records every fetched item, not only matched items. Matching only controls which new items are reported.
Storage
SQLite is used as durable local state. The seen_items table stores:
sourceitem_idtitleurlfirst_seen_atlast_seen_atmetadata_json
The primary key is (source, item_id), which allows one database to store items
from multiple sources without collisions.
On a fresh database, all currently visible matching items are considered new. After that, only previously unseen matching items trigger notifications.
Polling Jitter
Watch mode uses:
polling:
interval_seconds: 3600
jitter_seconds: 600
With this configuration, checks happen every 3000 to 4200 seconds. This avoids requesting the source at exactly the same time every hour.
Development
Run tests:
pytest
Run a syntax check:
python3 -m compileall src tests
Current Limitations
- TK Maxx is the only implemented production source.
- Telegram notifications are text-only; product images are parsed but not sent.
- Watch mode runs as a foreground process, not as an installed service.
- Notification batching and retry policies are intentionally minimal.
License
MIT License. See LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file signalwatch-0.1.0.tar.gz.
File metadata
- Download URL: signalwatch-0.1.0.tar.gz
- Upload date:
- Size: 22.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7aaa2a0761d3b2dca2b2a9302fca5242a708a52f440e402b4bac6e0afaa5f49e
|
|
| MD5 |
aa73f852818ae9ab20d25b7df00e1bf5
|
|
| BLAKE2b-256 |
af4df794a70ba88e7783b6130564314f0ffa69b5b672fd554c2c5824db70bca8
|
File details
Details for the file signalwatch-0.1.0-py3-none-any.whl.
File metadata
- Download URL: signalwatch-0.1.0-py3-none-any.whl
- Upload date:
- Size: 21.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5e5daf8a56fddec627e351b117c0daaadc1f6cde15350fcd1e5a12c763e6cea6
|
|
| MD5 |
182eafac7f1d1d50f06e998244f1c0b8
|
|
| BLAKE2b-256 |
5245ea5dc3ae722c65cf226cc988b9f0ce017071c2cf60679aaac2c612b90683
|