""" Wiki Configuration Manager - Fetches post templates and titles from subreddit wiki """ import time import json import re import yaml from typing import Dict, Optional, Tuple import config # Cache TTL in seconds (refresh wiki config every 30 minutes) WIKI_CACHE_TTL = 1800 class WikiConfig: """Manages post configurations loaded from subreddit wiki.""" def __init__(self): self.configs: Dict[str, Dict[str, str]] = {} self.default_config: Dict[str, str] = {"title": "", "body": ""} self.last_updated = 0 self.reddit = None self.subreddit_name = None def init(self, reddit, subreddit_name: str): """Initialize the wiki config manager.""" self.reddit = reddit self.subreddit_name = subreddit_name def should_refresh(self) -> bool: """Check if cache has expired.""" return (time.time() - self.last_updated) >= WIKI_CACHE_TTL def fetch_from_wiki(self) -> bool: """ Fetch post configurations from subreddit wiki. Wiki page format (YAML): ```yaml release: title: "Minecraft {version} Released!" body: | # Minecraft {version} Released A new version of Minecraft is available! **Version:** {version} **Date:** {release_date} Get it now at [minecraft.net](https://minecraft.net) snapshot: title: "Minecraft {version} Snapshot Available" body: | # Minecraft {version} Snapshot A new snapshot is available for testing! **Version:** {version} **Date:** {release_date} Try it in the launcher! default: title: "Minecraft {version} ({type})" body: | New {type}: {version} Released: {release_date} ``` Returns: True if successful, False otherwise """ try: subreddit = self.reddit.subreddit(self.subreddit_name) print(f"[WIKI_CONFIG] Attempting to fetch wiki page: {config.WIKI_PAGE_NAME}") # Try the wiki page with the configured name wiki_page = subreddit.wiki[config.WIKI_PAGE_NAME] content = wiki_page.content_md self.configs = self._parse_yaml_content(content) self.last_updated = time.time() if self.configs: print(f"[WIKI_CONFIG] ✓ Loaded {len(self.configs)} configuration(s)") for release_type in self.configs: print(f" - {release_type}") return True else: print("[WIKI_CONFIG] ⚠ No configurations found in wiki") return False except Exception as e: print(f"[WIKI_CONFIG] ✗ Error fetching wiki page '{config.WIKI_PAGE_NAME}' from r/{self.subreddit_name}: {e}") print(f"[WIKI_CONFIG] ⚠ Check that the page exists at reddit.com/r/{self.subreddit_name}/wiki/{config.WIKI_PAGE_NAME}") return False def _parse_yaml_content(self, content: str) -> Dict[str, Dict[str, str]]: """ Parse YAML content into configuration dict. Expected format: ```yaml release: title: "Minecraft {version} Released!" body: | Multi-line post body with {placeholders} snapshot: title: "Minecraft {version} Snapshot" body: | Snapshot post body ``` Returns: Dict mapping release_type -> {"title": str, "body": str} """ try: data = yaml.safe_load(content) if not isinstance(data, dict): print("[WIKI_CONFIG] ✗ Wiki content is not valid YAML dictionary") return {} configs = {} for release_type, config in data.items(): if isinstance(config, dict): if "title" in config and "body" in config: configs[release_type.lower()] = { "title": str(config["title"]), "body": str(config["body"]) } else: print(f"[WIKI_CONFIG] ⚠ Missing 'title' or 'body' for {release_type}") return configs except yaml.YAMLError as e: print(f"[WIKI_CONFIG] ✗ YAML parsing error: {e}") return {} def get_config(self, release_type: str, refresh: bool = False) -> Tuple[str, str]: """ Get title and body template for a release type. Args: release_type: Type like "release" or "snapshot" refresh: Force refresh from wiki Returns: Tuple of (title_template, body_template) """ # Refresh if needed if refresh or self.should_refresh() or not self.configs: self.fetch_from_wiki() # Get config for this type, fall back to any available config if release_type in self.configs: config = self.configs[release_type] return config["title"], config["body"] # Try generic "default" config if "default" in self.configs: config = self.configs["default"] return config["title"], config["body"] # Fall back to hardcoded defaults default_title = "Minecraft {version} Released!" default_body = """# Minecraft {version} A new version is available! **Version:** {version} **Released:** {release_date} Get it at [minecraft.net](https://minecraft.net)""" return default_title, default_body def format_post(self, release_type: str, version: str, release_date: str) -> Tuple[str, str]: """ Get formatted post title and body for a version. Args: release_type: Type like "release" or "snapshot" version: Version string like "1.21" release_date: Formatted date string Returns: Tuple of (formatted_title, formatted_body) """ title_template, body_template = self.get_config(release_type) # Format with available placeholders format_dict = { "version": version, "release_date": release_date, "type": release_type } try: formatted_title = title_template.format(**format_dict) formatted_body = body_template.format(**format_dict) return formatted_title, formatted_body except KeyError as e: print(f"[WIKI_CONFIG] ✗ Unknown placeholder in template: {e}") # Fall back to defaults formatted_title = f"Minecraft {version} ({release_type})" formatted_body = f"New {release_type}: {version}\nReleased: {release_date}" return formatted_title, formatted_body