Claude f13bfd7b07 Default ITAD_DEALS_LIMIT to 200 (API max) to maximise deal coverage
Since the ITAD API only sorts by discount or price (no time-based sort),
fetching the full 200-deal window per country ensures our client-side
filtering sees every available deal rather than just the top N by discount.
The dedup database already prevents reposting, so the extra data is cheap.

https://claude.ai/code/session_01EfPjktyrF24DBNHWsY1KBP
2026-02-28 23:42:54 +00:00
2026-02-28 00:00:22 +00:00
2026-02-28 00:00:22 +00:00
2026-02-27 15:47:43 -08:00

Pastel

A Matrix bot that posts gaming deals and free game alerts to a specified Matrix room.

Deals are sourced from PC/digital storefronts only (Steam, GOG, Humble Store, GreenManGaming, Epic Games Store) — universally accessible regardless of region.

Data Sources

  • CheapShark — polled every 2 hours for top deals across Steam, GOG, Humble Store, and GreenManGaming
  • IsThereAnyDeal — polled every 2 hours for deals across all tracked stores, with built-in historical low detection (requires API key)
  • Epic Games Store — polled daily for free game promotions

CheapShark and IsThereAnyDeal can be used individually or together — configure via the DEAL_SOURCES variable. When used as a deal source, IsThereAnyDeal provides historical low flags directly. When only CheapShark is active, IsThereAnyDeal can still optionally enrich deals with historical low info via the ITAD_API_KEY.

Quick Start

  1. Copy .env.example to .env and fill in your Matrix credentials and room ID
  2. Run with Docker:
docker build -t pastel .
docker run --env-file .env -v pastel-data:/data pastel

Or run directly with Python 3.12+:

pip install -r requirements.txt
python -m gaming_deals_bot

Obtaining a Matrix Bot Access Token

  1. Create a bot account on your homeserver (e.g. via Element: register a new account like @dealsbot:example.com).

  2. Log in and get the access token using curl:

    curl -XPOST "https://matrix.example.com/_matrix/client/v3/login" \
      -H "Content-Type: application/json" \
      -d '{
        "type": "m.login.password",
        "identifier": { "type": "m.id.user", "user": "dealsbot" },
        "password": "YOUR_PASSWORD"
      }'
    

    The response will contain an access_token field — copy that value into your .env as MATRIX_BOT_ACCESS_TOKEN.

  3. Invite the bot to your deals room, then have the bot accept the invite (the bot does this automatically on startup).

Tip: After extracting the token you can change the bot account's password without invalidating the token. Store the token securely — anyone with it can act as the bot.

Configuration

All configuration is via environment variables (see .env.example):

Core

Variable Required Default Description
MATRIX_HOMESERVER_URL Yes Matrix homeserver URL
MATRIX_BOT_USER_ID Yes Bot's Matrix user ID
MATRIX_BOT_ACCESS_TOKEN Yes Bot's access token
MATRIX_DEALS_ROOM_ID Yes Room ID to post deals in
ITAD_API_KEY No IsThereAnyDeal API key (required when itad is in DEAL_SOURCES, optional otherwise for historical low detection)
DEAL_SOURCES No cheapshark Comma-separated deal sources: cheapshark, itad, or cheapshark,itad
ITAD_COUNTRIES No US Comma-separated ISO 3166-1 alpha-2 country codes to fetch ITAD deals from (e.g. US,CA,GB,DE)
DEFAULT_CURRENCY No USD Primary display currency shown first in price strings
EXTRA_CURRENCIES No CAD,EUR,GBP Additional currencies shown after the default (comma-separated)
SEND_INTRO_MESSAGE No false Send "The deals must flow." to the room on startup
DATABASE_PATH No deals.db Path to SQLite database file

Filtering

Each deal source has its own filter settings. Source-specific values take priority; when not set they fall back to the shared defaults.

Variable Source Default Description
CHEAPSHARK_MIN_DISCOUNT CheapShark 50 Minimum discount percentage
CHEAPSHARK_MIN_RATING CheapShark 8.0 Minimum deal rating (0-10, 0 = unrated allowed)
CHEAPSHARK_MAX_PRICE CheapShark 20 Maximum sale price (USD)
ITAD_MIN_DISCOUNT ITAD 50 Minimum discount percentage
ITAD_MAX_PRICE ITAD 20 Maximum sale price (USD, prices from other regions are converted)
ITAD_DEALS_LIMIT ITAD 200 Number of deals to fetch per country (max 200)
MIN_DISCOUNT_PERCENT Shared 50 Fallback minimum discount when source-specific value is not set
MAX_PRICE Shared 20 Fallback maximum price when source-specific value is not set

Preflight Check

Run --check to validate your configuration and test connectivity to all services before starting the bot:

python -m gaming_deals_bot --check

This verifies:

  • Matrix — authentication token is valid and bot has joined the target room
  • CheapShark — API is reachable (skipped if not in DEAL_SOURCES)
  • Epic Games Store — API is reachable
  • Frankfurter — exchange rate API is reachable
  • IsThereAnyDeal — API key is valid (required when itad is in DEAL_SOURCES, skipped otherwise if not configured)

The command exits with code 0 on success and 1 on failure, so it works in CI and Docker health-checks.

Behavior

  • First run: fetches current deals and records them in the database without posting (avoids spamming the room with existing deals)
  • Deduplication: deals are tracked by game ID + timestamp; duplicates are never reposted
  • Pruning: deals older than 30 days are pruned from the database so they can be reposted if they return
  • One message per deal: each deal is posted individually so messages are independently linkable and dismissible
  • Multi-currency pricing: deal prices are shown in your configured currencies (default: USD, CAD, EUR, GBP) using live exchange rates from the Frankfurter API (ECB data, no API key required). Set DEFAULT_CURRENCY to change the primary display currency and EXTRA_CURRENCIES for additional ones. Rates are cached and refreshed twice daily.
  • Multi-country ITAD deals: when using IsThereAnyDeal, deals can be fetched from multiple countries simultaneously via ITAD_COUNTRIES (e.g. US,CA,GB,DE). Deals are merged and deduplicated, with the first country in the list taking priority for duplicate games.
Description
A Matrix bot that posts gaming deals and free game alerts to a specified Matrix room.
Readme Apache-2.0 148 KiB
Languages
Go 97.7%
Python 2.3%