When MATRIX_USE_THREADS=true, deals are posted into dedicated threads
instead of the room timeline:
- 🎮 Game Deals — CheapShark + ITAD type=game
- 🧩 DLC Deals — ITAD type=dlc
- 🆓 Epic Free Games — current and upcoming Epic free games
- 📦 Non-Game Deals — ITAD non-game content (software, courses, etc.)
Thread roots are created on first use and persisted in the database.
When threads are disabled (default), behaviour is unchanged.
Key changes:
- New threads.py module with ThreadCategory enum and routing logic
- ITADDeal now carries deal_type; type filter moved from fetcher to bot
- MatrixDealsClient gains send_deal_in_thread() and create_thread_root()
- Database gets thread_roots table for storing root event IDs
- Bot routes each deal to the appropriate thread via _send_to_thread_or_room()
https://claude.ai/code/session_01EfPjktyrF24DBNHWsY1KBP
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
- ITAD deals can now be fetched from multiple countries simultaneously via
ITAD_COUNTRIES (e.g. US,CA,GB,DE). Deals are merged across regions and
deduplicated by game+shop, with the first country taking priority.
- Prices from non-USD regions are normalised to USD using exchange rates
so filtering (max price) works consistently across countries.
- ITAD results are now sorted by newest deals first (client-side by
timestamp) instead of only by highest discount, reducing missed deals.
- Default fetch limit raised from 20 to 100 to capture more deals.
- Display currency is now configurable: DEFAULT_CURRENCY sets the primary
currency shown first, EXTRA_CURRENCIES sets additional ones. All
Frankfurter-supported currencies are available with proper symbols.
- Filtering is now per-source with dedicated env vars:
CHEAPSHARK_MIN_DISCOUNT, CHEAPSHARK_MIN_RATING, CHEAPSHARK_MAX_PRICE,
ITAD_MIN_DISCOUNT, ITAD_MAX_PRICE, ITAD_DEALS_LIMIT. Shared fallbacks
(MIN_DISCOUNT_PERCENT, MAX_PRICE) are still supported. Legacy
MAX_PRICE_USD and MIN_DEAL_RATING continue to work as fallbacks.
https://claude.ai/code/session_01EfPjktyrF24DBNHWsY1KBP
The previous 0-100 scale with a * 10 conversion was confusing —
CheapShark returns deal ratings as floats (e.g. 9.8, 7.5) so the
config should match. Default is now 8.0 instead of 80.
https://claude.ai/code/session_01LPpSZFfyh6vdV5HGFWjoQX
`python -m gaming_deals_bot --check` tests each external dependency
before starting the bot:
- Matrix: verifies access token (whoami) and room membership
- CheapShark: hits the deals endpoint
- Epic Games Store: hits the free-games endpoint
- Frankfurter: fetches exchange rates
- IsThereAnyDeal: validates the API key (skipped if not set)
Exits 0/1 so it works in CI pipelines and Docker health-checks.
https://claude.ai/code/session_01LPpSZFfyh6vdV5HGFWjoQX
Fetches live exchange rates from the Frankfurter API (ECB data, free,
no API key) and displays converted prices alongside USD in every deal
message. Rates are cached in memory and auto-refreshed hourly.
https://claude.ai/code/session_01LPpSZFfyh6vdV5HGFWjoQX
Implements a Matrix bot that posts PC gaming deals and free game alerts:
- CheapShark API integration (Steam, GOG, Humble, GMG) polled every 2 hours
- Epic Games Store free games detection polled daily
- IsThereAnyDeal historical low price flagging (optional)
- SQLite deduplication with 30-day pruning
- First-run population (records existing deals without posting)
- Matrix-flavored HTML + plain text fallback messages
- Dockerfile for containerized deployment
https://claude.ai/code/session_01LPpSZFfyh6vdV5HGFWjoQX