Skip to main content

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 WatchItem domain model.
  • Persists seen items in SQLite with first_seen_at and last_seen_at timestamps.
  • 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

  1. Create a bot with @BotFather.
  2. Send /start to the bot.
  3. Fetch updates to find your chat ID:
curl "https://api.telegram.org/bot<TOKEN>/getUpdates"
  1. Export the required environment variables:
export SIGNALWATCH_TELEGRAM_BOT_TOKEN="<TOKEN>"
export SIGNALWATCH_TELEGRAM_CHAT_ID="<CHAT_ID>"
  1. 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:

  • source
  • item_id
  • title
  • url
  • first_seen_at
  • last_seen_at
  • metadata_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.

Release files for signalwatch 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for signalwatch 0.1.0
File Size Uploaded
signalwatch-0.1.0.tar.gz 22.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for signalwatch 0.1.0
File Interpreter ABI Platform
signalwatch-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 43.9 kB

Release files / signalwatch-0.1.0.tar.gz

Download URL signalwatch-0.1.0.tar.gz
Size 22.2 kB
Tags Source
SHA-256 checksum
How to use checksums
7aaa2a0761d3b2dca2b2a9302fca5242a708a52f440e402b4bac6e0afaa5f49e
BLAKE2b-256 checksum
How to use checksums
af4df794a70ba88e7783b6130564314f0ffa69b5b672fd554c2c5824db70bca8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.3

Release files / signalwatch-0.1.0-py3-none-any.whl

Download URL signalwatch-0.1.0-py3-none-any.whl
Size 21.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
5e5daf8a56fddec627e351b117c0daaadc1f6cde15350fcd1e5a12c763e6cea6
BLAKE2b-256 checksum
How to use checksums
5245ea5dc3ae722c65cf226cc988b9f0ce017071c2cf60679aaac2c612b90683
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.3

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page