|
@@ -0,0 +1,144 @@
|
|
|
+#
|
|
|
+# This file is part of stov, written by Helmut Pozimski 2012-2017.
|
|
|
+#
|
|
|
+# 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 <http://www.gnu.org/licenses/>.
|
|
|
+
|
|
|
+
|
|
|
+# -*- coding: utf8 -*-
|
|
|
+
|
|
|
+""" This module implements support for subscriptions from the ZDF Mediathek"""
|
|
|
+
|
|
|
+import json
|
|
|
+import logging
|
|
|
+import urllib.request
|
|
|
+from datetime import datetime, timedelta
|
|
|
+
|
|
|
+from lib_stov import stov_exceptions
|
|
|
+
|
|
|
+LOGGER = logging.getLogger("stov")
|
|
|
+
|
|
|
+
|
|
|
+class ZDFChannel(object):
|
|
|
+ """Stores the relevant attributes of a ZDF Mediathek channel"""
|
|
|
+ def __init__(self, title, 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, conf):
|
|
|
+ if subscription_type == "user":
|
|
|
+ self._type = "channel"
|
|
|
+ else:
|
|
|
+ self._type = subscription_type
|
|
|
+ self._name = name
|
|
|
+ self._conf = conf
|
|
|
+ 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
|
|
|
+ """
|
|
|
+ videos_list = []
|
|
|
+ new_videos = []
|
|
|
+ today = datetime.today()
|
|
|
+ connection = urllib.request.urlopen(
|
|
|
+ "https://zdf-cdn.live.cellular.de/mediathekV2/broadcast-missed/%s"
|
|
|
+ % (today-timedelta(days=1)).strftime("%Y-%m-%d"))
|
|
|
+ response = json.load(connection)
|
|
|
+ for cluster in response["broadcastCluster"]:
|
|
|
+ for broadcast in cluster["teaser"]:
|
|
|
+ if self._name in broadcast["titel"]:
|
|
|
+ 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
|
|
|
+ else:
|
|
|
+ LOGGER.debug(_("Could not determine an itag value "
|
|
|
+ "from the configuration"))
|
|
|
+ return "hls-3286"
|