from datetime import timedelta
import requests
from lib.db.cached import MemoryCache
from lib.utils.kodi.utils import kodilog
INTRODB_BASE_URL = "http://api.introdb.app"
INTRODB_TIMEOUT = 5
INTRODB_CACHE_EXPIRY = timedelta(hours=24)
_cache = MemoryCache(database="introdb")
_SENTINEL = "__introdb_none__"
def get_segments(imdb_id, season, episode):
"""
Fetch intro/recap/outro segment timestamps from IntroDB for a given episode.
Results are cached in memory for 24 hours to avoid redundant API calls.
Args:
imdb_id: IMDb ID string (e.g., "tt0944947")
season: Season number (int)
episode: Episode number (int)
Returns:
dict with keys 'intro', 'recap', 'outro' (each a dict or None),
or None if the request fails or no data is available.
"""
if not imdb_id or not season or not episode:
return None
cache_key = f"{imdb_id}.S{season}E{episode}"
request_params = {
"imdb_id": imdb_id,
"season": int(season),
"episode": int(episode),
}
kodilog(f"IntroDB: get_segments called for {imdb_id} S{season}E{episode}")
# Check cache first
cached = _cache.get(cache_key)
if cached is not None:
if cached == _SENTINEL:
kodilog(f"IntroDB: Cache hit (no data) for {imdb_id} S{season}E{episode}")
return None
kodilog(f"IntroDB: Cache hit for {imdb_id} S{season}E{episode} data={cached}")
return cached
try:
kodilog(
f"IntroDB: Requesting /segments for {imdb_id} S{season}E{episode} with params {request_params}"
)
response = requests.get(
f"{INTRODB_BASE_URL}/segments",
params=request_params,
timeout=INTRODB_TIMEOUT,
)
kodilog(
f"IntroDB: Response status {response.status_code} for {imdb_id} S{season}E{episode} body={response.text}"
)
if response.status_code == 404:
kodilog(f"IntroDB: No segments found for {imdb_id} S{season}E{episode}")
_cache.set(cache_key, _SENTINEL, expires=INTRODB_CACHE_EXPIRY)
return None
if response.status_code != 200:
kodilog(
f"IntroDB: Unexpected status {response.status_code} for {imdb_id} S{season}E{episode}"
)
return None
data = response.json()
kodilog(
f"IntroDB: Got segments for {imdb_id} S{season}E{episode}: "
f"intro={'yes' if data.get('intro') else 'no'}, "
f"recap={'yes' if data.get('recap') else 'no'}, "
f"outro={'yes' if data.get('outro') else 'no'}"
)
_cache.set(cache_key, data, expires=INTRODB_CACHE_EXPIRY)
return data
except requests.exceptions.Timeout:
kodilog(f"IntroDB: Request timed out for {imdb_id} S{season}E{episode}")
return None
except requests.exceptions.RequestException as e:
kodilog(f"IntroDB: Request failed for {imdb_id} S{season}E{episode}: {e}")
return None
except (ValueError, KeyError) as e:
kodilog(f"IntroDB: Failed to parse response for {imdb_id} S{season}E{episode}: {e}")
return None