# # This file is part of stov, written by Helmut Pozimski 2012-2018. # # stov is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, version 2 of the License. # # stov is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with stov. If not, see . # -*- coding: utf8 -*- """ This module implements support for subscriptions from the ZDF Mediathek""" import json import logging import urllib.request import urllib.error import socket from datetime import datetime, timedelta from lib_stov import stov_exceptions from lib_stov import configuration LOGGER = logging.getLogger("stov") class ZDFChannel(object): """Stores the relevant attributes of a ZDF Mediathek channel""" def __init__(self, title, videos=None): if videos is None: videos = [] self.title = title self.videos = videos self.type = "channel" class ZDFVideo(object): """Stores the relevant attributes of a single video in the ZDF Mediathek """ def __init__(self, title, url): self.title = title self.video_id = url class Connector(object): """Connector class performing operations against the API""" def __init__(self, subscription_type, name, search=""): if subscription_type == "user": self._type = "channel" else: self._type = subscription_type self._name = name self._conf = configuration.Conf.get_instance() self._search = search if self._type != "channel": raise stov_exceptions.TypeNotSupported() def _fetch_videos(self, existing_videos): """ Fetches the videos of the day before from the ZDF API and returns a list of newly added videos. :param existing_videos: videos that already exist in the database :type existing_videos: list :return: List of all newly retrieved videos :rtype: list """ name_found = False videos_list = [] new_videos = [] today = datetime.today() for i in range(7, -1, -1): day = (today - timedelta(days=i)).strftime("%Y-%m-%d") try: connection = urllib.request.urlopen( "https://zdf-cdn.live.cellular.de/mediathekV2/broadcast-" "missed/%s" % day, timeout=10) data = connection.read().decode("utf-8") except urllib.error.HTTPError: LOGGER.error("Error while fetching ZDF data for %s", day) except socket.timeout: LOGGER.error("Connection timed out while fetching ZDF data " "for %s", day) else: response = json.loads(data) for cluster in response["broadcastCluster"]: for broadcast in cluster["teaser"]: try: name_found = self._name in broadcast["brandTitle"] except KeyError: name_found = self._name in broadcast["headline"] if name_found: if self._search: if self._search in broadcast["titel"]: new_videos.append((broadcast["sharingUrl"], broadcast["titel"])) else: new_videos.append((broadcast["sharingUrl"], broadcast["titel"])) if new_videos: for broadcast in new_videos: video_exists = False if existing_videos: for existing_video in existing_videos: if broadcast[0] == existing_video.site_id: video_exists = True break if not video_exists: videos_list.append(ZDFVideo(broadcast[1], broadcast[0])) return videos_list def parse_api_data(self, existing_videos): """ Takes the existing videos passed to it and wraps them into a channel object. :param existing_videos: list of existing_videos :type existing_videos: list :return: Channel object :rtype: ZDFChannel """ videos = self._fetch_videos(existing_videos) channel = ZDFChannel(self._name, videos) return channel @staticmethod def construct_video_url(url): """ Compatibility method, just returns the url :param url: The url to return :type url: str :return: url :rtype: str """ return url @staticmethod def get_quality_parameter(config): """ Determines which quality value results from codec and resolution settings and returns it :param config: configuration object :type config: lib_stov.configuration.Conf :return: itag value :rtype: str """ LOGGER.debug(_("Trying to determine the itag value for youtube-dl from" " your quality and codec settings.")) quality_value = "" if config.values["videocodec"] == "flv": if config.values["maxresolution"] == "480p": quality_value = "hds-1489" elif config.values["videocodec"] == "mp4": if config.values["maxresolution"] == "720p": quality_value = "hls-3286" if quality_value: LOGGER.debug(_("Found value: %s."), quality_value) return quality_value + "/" + config.values["videocodec"] LOGGER.debug(_("Could not determine an itag value " "from the configuration")) return "hls-3286" + "/" + config.values["videocodec"]