"""Bible Stories data loader. Loads all story JSON files and provides access to stories by category and slug. """ import json from functools import lru_cache from pathlib import Path from typing import Optional # Path to stories directory STORIES_DIR = Path(__file__).parent / "data" / "stories" def _load_all_stories_uncached() -> list[dict]: """Load all story categories from JSON files (internal, uncached).""" categories = [] if not STORIES_DIR.exists(): return categories # Load JSON files in order (they're numbered) json_files = sorted(STORIES_DIR.glob("*.json")) for json_file in json_files: try: with open(json_file, "r", encoding="utf-8") as f: category_data = json.load(f) categories.append(category_data) except (json.JSONDecodeError, IOError) as e: print(f"Error loading {json_file}: {e}") continue return categories # Load stories once at module import time _STORIES_CACHE: list[dict] | None = None def load_all_stories() -> list[dict]: """Load all story categories from JSON files (cached).""" global _STORIES_CACHE if _STORIES_CACHE is None: _STORIES_CACHE = _load_all_stories_uncached() return _STORIES_CACHE def get_all_stories_flat() -> list[dict]: """Get all stories as a flat list with category info attached.""" categories = load_all_stories() all_stories = [] for category in categories: category_name = category.get("category", "Unknown") category_slug = category.get("slug", "unknown") for story in category.get("stories", []): story_with_category = story.copy() story_with_category["category_name"] = category_name story_with_category["category_slug"] = category_slug all_stories.append(story_with_category) return all_stories def get_story_by_slug(slug: str) -> Optional[dict]: """Find a story by its slug.""" for story in get_all_stories_flat(): if story.get("slug") == slug: return story return None def get_stories_by_category(category_slug: str) -> list[dict]: """Get all stories in a specific category.""" categories = load_all_stories() for category in categories: if category.get("slug") == category_slug: stories = [] for story in category.get("stories", []): story_with_category = story.copy() story_with_category["category_name"] = category.get("category", "Unknown") story_with_category["category_slug"] = category_slug stories.append(story_with_category) return stories return [] def get_category_by_slug(category_slug: str) -> Optional[dict]: """Get a category by its slug.""" categories = load_all_stories() for category in categories: if category.get("slug") == category_slug: return category return None # Cache story counts _CACHED_STORY_COUNT = None _CACHED_CATEGORY_COUNT = None def get_story_count() -> int: """Get total number of stories (cached).""" global _CACHED_STORY_COUNT if _CACHED_STORY_COUNT is None: _CACHED_STORY_COUNT = len(get_all_stories_flat()) return _CACHED_STORY_COUNT def get_category_count() -> int: """Get total number of categories (cached).""" global _CACHED_CATEGORY_COUNT if _CACHED_CATEGORY_COUNT is None: _CACHED_CATEGORY_COUNT = len(load_all_stories()) return _CACHED_CATEGORY_COUNT # Pre-load categories on module import for faster access STORY_CATEGORIES = None def get_categories() -> list[dict]: """Get all categories (cached).""" global STORY_CATEGORIES if STORY_CATEGORIES is None: STORY_CATEGORIES = load_all_stories() return STORY_CATEGORIES def refresh_stories(): """Refresh the cached stories (useful after adding new files).""" global STORY_CATEGORIES, _CACHED_STORY_COUNT, _CACHED_CATEGORY_COUNT STORY_CATEGORIES = load_all_stories() _CACHED_STORY_COUNT = None _CACHED_CATEGORY_COUNT = None