# Licence: GNU AGPL v3: http://www.gnu.org/licenses/ # This file is part of [`delarte`](https://git.afpy.org/fcode/delarte.git) """Provide ArteTV JSON API utilities.""" import json from http import HTTPStatus from urllib.request import urlopen def load_api_data(url): """Retrieve the root node (infamous "data") of an API call response.""" http_response = urlopen(url) if http_response.status != HTTPStatus.OK: raise RuntimeError("API request failed") if ( http_response.getheader("Content-Type") != "application/vnd.api+json; charset=utf-8" ): raise ValueError("API response not supported") return json.load(http_response)["data"] def load_config(lang, program_id): """Retrieve a program config from API.""" url = f"https://api.arte.tv/api/player/v2/config/{lang}/{program_id}" config = load_api_data(url) if config["type"] != "ConfigPlayer": raise ValueError("Invalid API response") if config["attributes"]["metadata"]["providerId"] != program_id: raise ValueError("Invalid API response") return config def iter_renditions(config): """Return a rendition (code, label) iterator.""" for stream in config["attributes"]["streams"]: yield ( # rendition code stream["versions"][0]["eStat"]["ml5"], # rendition full name stream["versions"][0]["label"], ) def select_rendition(config, rendition_code): """Return the master playlist index url for the given rendition code.""" for stream in config["attributes"]["streams"]: if stream["versions"][0]["eStat"]["ml5"] == rendition_code: return stream["url"] return None