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
60 lines
1.9 KiB
Python
60 lines
1.9 KiB
Python
"""Thread category definitions for Matrix room threads.
|
|
|
|
When ``MATRIX_USE_THREADS=true``, deal messages are posted inside
|
|
per-category threads rather than directly into the room timeline.
|
|
"""
|
|
|
|
from enum import Enum
|
|
from html import escape
|
|
|
|
|
|
class ThreadCategory(str, Enum):
|
|
"""Categories that map to distinct Matrix threads."""
|
|
|
|
GAME_DEALS = "game_deals"
|
|
DLC_DEALS = "dlc_deals"
|
|
EPIC_FREE = "epic_free"
|
|
NON_GAME_DEALS = "non_game_deals"
|
|
|
|
|
|
# Display metadata for each thread category.
|
|
# ``label`` is the thread root title; ``description`` appears below it.
|
|
THREAD_META: dict[ThreadCategory, dict[str, str]] = {
|
|
ThreadCategory.GAME_DEALS: {
|
|
"label": "🎮 Game Deals",
|
|
"description": "PC game deals from CheapShark and IsThereAnyDeal",
|
|
},
|
|
ThreadCategory.DLC_DEALS: {
|
|
"label": "🧩 DLC Deals",
|
|
"description": "DLC and expansion deals from IsThereAnyDeal",
|
|
},
|
|
ThreadCategory.EPIC_FREE: {
|
|
"label": "🆓 Epic Free Games",
|
|
"description": "Weekly free games from the Epic Games Store",
|
|
},
|
|
ThreadCategory.NON_GAME_DEALS: {
|
|
"label": "📦 Non-Game Deals",
|
|
"description": "Software, courses, and other non-game deals",
|
|
},
|
|
}
|
|
|
|
|
|
def itad_type_to_category(deal_type: str) -> ThreadCategory:
|
|
"""Map an ITAD ``type`` value to a thread category."""
|
|
if deal_type == "game":
|
|
return ThreadCategory.GAME_DEALS
|
|
if deal_type == "dlc":
|
|
return ThreadCategory.DLC_DEALS
|
|
return ThreadCategory.NON_GAME_DEALS
|
|
|
|
|
|
def format_thread_root(category: ThreadCategory) -> tuple[str, str]:
|
|
"""Return ``(plain_text, html)`` for a thread root message."""
|
|
meta = THREAD_META[category]
|
|
label = meta["label"]
|
|
desc = meta["description"]
|
|
|
|
plain_text = f"{label}\n{desc}"
|
|
html = f"<strong>{escape(label)}</strong><br>\n<em>{escape(desc)}</em>"
|
|
return plain_text, html
|