Files
Pastel/gaming_deals_bot/config.py
Claude e4d90d0331 Add multi-country ITAD deals, configurable currency, and per-source filtering
- 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
2026-02-28 23:40:36 +00:00

79 lines
3.1 KiB
Python

import os
class Config:
"""Bot configuration loaded from environment variables."""
def __init__(self):
# Matrix settings
self.matrix_homeserver_url = self._require("MATRIX_HOMESERVER_URL")
self.matrix_bot_user_id = self._require("MATRIX_BOT_USER_ID")
self.matrix_bot_access_token = self._require("MATRIX_BOT_ACCESS_TOKEN")
self.matrix_deals_room_id = self._require("MATRIX_DEALS_ROOM_ID")
# ITAD API key (optional — historical low checks disabled without it)
self.itad_api_key = os.environ.get("ITAD_API_KEY", "")
# Deal sources: comma-separated list of "cheapshark", "itad" (default: cheapshark)
raw_sources = os.environ.get("DEAL_SOURCES", "cheapshark")
self.deal_sources: list[str] = [
s.strip().lower() for s in raw_sources.split(",") if s.strip()
]
# ITAD countries: comma-separated ISO 3166-1 alpha-2 country codes
# Deals are fetched for each country and merged (first country has priority
# when the same game appears in multiple regions).
raw_countries = os.environ.get("ITAD_COUNTRIES", "US")
self.itad_countries: list[str] = [
c.strip().upper() for c in raw_countries.split(",") if c.strip()
]
# Currency display
self.default_currency = os.environ.get("DEFAULT_CURRENCY", "USD").upper()
raw_extra = os.environ.get("EXTRA_CURRENCIES", "CAD,EUR,GBP")
self.extra_currencies: list[str] = [
c.strip().upper() for c in raw_extra.split(",") if c.strip()
]
# Shared filter fallbacks (support legacy env vars)
_max_price = os.environ.get(
"MAX_PRICE", os.environ.get("MAX_PRICE_USD", "20")
)
_min_discount = os.environ.get("MIN_DISCOUNT_PERCENT", "50")
_min_rating = os.environ.get("MIN_DEAL_RATING", "8.0")
# CheapShark-specific filtering (falls back to shared values)
self.cheapshark_min_discount = int(
os.environ.get("CHEAPSHARK_MIN_DISCOUNT", _min_discount)
)
self.cheapshark_min_rating = float(
os.environ.get("CHEAPSHARK_MIN_RATING", _min_rating)
)
self.cheapshark_max_price = float(
os.environ.get("CHEAPSHARK_MAX_PRICE", _max_price)
)
# ITAD-specific filtering (falls back to shared values)
self.itad_min_discount = int(
os.environ.get("ITAD_MIN_DISCOUNT", _min_discount)
)
self.itad_max_price = float(
os.environ.get("ITAD_MAX_PRICE", _max_price)
)
self.itad_deals_limit = int(os.environ.get("ITAD_DEALS_LIMIT", "100"))
# Intro message on startup
self.send_intro_message = os.environ.get(
"SEND_INTRO_MESSAGE", "false"
).lower() in ("true", "1", "yes")
# Database
self.database_path = os.environ.get("DATABASE_PATH", "deals.db")
@staticmethod
def _require(name: str) -> str:
value = os.environ.get(name)
if not value:
raise ValueError(f"Required environment variable {name} is not set")
return value