Files
HomeAssistance/custom_components/teamtracker/provider_base.py
T
2026-06-05 22:34:31 -04:00

106 lines
3.5 KiB
Python

""" Base class for all data providers """
from __future__ import annotations
from abc import ABC, abstractmethod
from datetime import datetime, timedelta, timezone
from typing import TYPE_CHECKING
from homeassistant.core import HomeAssistant
from .const import DOMAIN
if TYPE_CHECKING:
from .coordinator import TeamTrackerCoordinator
DEFAULT_DATA_FORMAT = "espn_json"
class BaseSportProvider(ABC):
"""Base class for all sport data providers."""
def __init__(self, coordinator: TeamTrackerCoordinator | None = None) -> None:
# Define the attributes that must be available on all providers
self.DATA_PROVIDER: str = "default"
self.ATTRIBUTION: str = ""
self.DEFAULT_REFRESH_RATE: timedelta = timedelta(minutes=10)
self.RAPID_REFRESH_RATE: timedelta = timedelta(seconds=5)
self.data_format = DEFAULT_DATA_FORMAT
self._coordinator = coordinator
if self._coordinator:
self.data_cache = self._coordinator.hass.data.setdefault(DOMAIN, {}).setdefault("data_cache", {})
else: # coordinator is None when called from Config Flow
self.data_cache = {}
self._USER_AGENT = (
"Mozilla/5.0 (Macintosh; Intel Mac OS X 11_6) AppleWebKit/605.1.15 (KHTML, like "
"Gecko) Version/15.0 Safari/605.1.15"
)
#
# async_update_sport_data()
#
async def async_update_sport_data(self) -> dict:
"""Determines to use cached data or API call (if exprired)"""
if not self._coordinator:
return {"data": None, "url": None, "timestamp": None}
#
# Return cached response if not expired
#
key = self._get_cache_key()
response = self.data_cache.get(key, {}).get("response", None)
if response:
expiration = datetime.fromisoformat(response["timestamp"]) + self._coordinator.update_interval
now = datetime.now(timezone.utc)
if now < expiration:
response.update({"cache_flag": True}) # Add key to indicate cache was used
return response
#
# Call API to get refreshed response and cache it
#
response = await self.async_fetch_scoreboard_data(self._coordinator.hass, self._coordinator.get_lang())
if response["data"] is not None:
self.data_cache.update({key: {"response": response}})
return response
#
# _get_cache_key()
#
@abstractmethod
def _get_cache_key(self) -> str:
"""Return cache key"""
pass # pylint: disable=unnecessary-pass
@abstractmethod
async def async_fetch_team_data(
self,
hass: HomeAssistant,
sport_path: str="",
league_path: str=""
) -> dict:
"""Fetch and return team data in the standard format."""
pass # pylint: disable=unnecessary-pass
@abstractmethod
async def async_fetch_scoreboard_data(
self,
hass,
lang: str,
) -> dict:
"""Fetch and return sport data in the standard format."""
pass # pylint: disable=unnecessary-pass
async def async_fetch_team_conference_id(
self,
hass: HomeAssistant,
sport_path: str,
league_path: str,
team_id: str
) -> str:
"""Fetch conference/group ID for a single team from the ESPN team detail API."""
return ""