123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145 |
- #
- # This file is part of stov, written by Helmut Pozimski 2012-2021.
- #
- # 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 socket
- import urllib.error
- import urllib.request
- from datetime import datetime, timedelta
- from lib_stov import configuration
- from lib_stov import stov_exceptions
- LOGGER = logging.getLogger("stov")
- class ZDFChannel:
- """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:
- """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:
- """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
|