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
Users can now choose between CheapShark, ITAD, or both via the
DEAL_SOURCES env var (comma-separated, default: "cheapshark"). When
"itad" is included, the bot polls GET /deals/v2 for current deals with
discount/price filtering and posts them with the same formatting style.
ITAD deals include built-in historical low detection via the API's
deal flags. Preflight checks enforce ITAD_API_KEY when ITAD is a
configured deal source.
https://claude.ai/code/session_01B7YPGrE3NatkwadCXVjv2j
When SEND_INTRO_MESSAGE=true, the bot sends "The deals must flow." as
an m.notice to the Matrix room right after startup, before the first
scheduled deal checks. Defaults to off.
https://claude.ai/code/session_017eMsVwUopgmnEyd6JJedpV
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
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