diff options
author | raptor2101 <raptor2101@mykolab.com> | 2016-12-20 20:40:30 +0100 |
---|---|---|
committer | raptor2101 <raptor2101@mykolab.com> | 2016-12-20 20:40:30 +0100 |
commit | 85bf4f9f1f76eb953c81cb34b35db72a2cca374f (patch) | |
tree | 8b5199ccc58b0df4fc8c91f700b6ec64211a8638 /plugin.video.mediathek | |
parent | d3de7572ca730a79571478d04df927c05b59b988 (diff) |
[plugin.video.mediathek] 0.8.1
Diffstat (limited to 'plugin.video.mediathek')
-rw-r--r-- | plugin.video.mediathek/addon.xml | 2 | ||||
-rw-r--r-- | plugin.video.mediathek/changelog.txt | 1 | ||||
-rw-r--r-- | plugin.video.mediathek/mediathek/arte.py | 83 | ||||
-rw-r--r-- | plugin.video.mediathek/mediathek/zdf.py | 20 | ||||
-rw-r--r-- | plugin.video.mediathek/simplexbmc.py | 68 |
5 files changed, 105 insertions, 69 deletions
diff --git a/plugin.video.mediathek/addon.xml b/plugin.video.mediathek/addon.xml index 146815b..da032f8 100644 --- a/plugin.video.mediathek/addon.xml +++ b/plugin.video.mediathek/addon.xml @@ -2,7 +2,7 @@ <addon id="plugin.video.mediathek" name="Mediathek" - version="0.8.0" + version="0.8.1" provider-name="Raptor 2101"> <requires> <import addon="xbmc.python" version="2.25.0"/> diff --git a/plugin.video.mediathek/changelog.txt b/plugin.video.mediathek/changelog.txt index aec52d2..77edc82 100644 --- a/plugin.video.mediathek/changelog.txt +++ b/plugin.video.mediathek/changelog.txt @@ -1,3 +1,4 @@ +0.8.1 - CHG: Recover ARTE Search and Browsing Functionality 0.8.0 - CHG: Version pump to seperate pre-krypton version and krypton version 0.7.5 - CHG: reimplement ZDF Mediathak (important: ZDF enforces TLSv1 with SNI enabled, what is only supported by python 2.7.9.) Temporaily fix ARTE diff --git a/plugin.video.mediathek/mediathek/arte.py b/plugin.video.mediathek/mediathek/arte.py index e0a158d..ac3fec6 100644 --- a/plugin.video.mediathek/mediathek/arte.py +++ b/plugin.video.mediathek/mediathek/arte.py @@ -15,10 +15,8 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. -import re, traceback, urllib,json; -from mediathek import * -from xml.dom import minidom -from xml.dom import Node; +import re, traceback,json; +from mediathek import *; from bs4 import BeautifulSoup; regex_dateString = re.compile("\\d{1,2} ((\\w{3})|(\\d{2})) \\d{4}"); @@ -43,14 +41,14 @@ class ARTEMediathek(Mediathek): return "ARTE"; @classmethod def isSearchable(self): - return False; + return True; def __init__(self, simpleXbmcGui): self.gui = simpleXbmcGui; self.rootLink = "http://www.arte.tv"; self.basePage = self.rootLink+"/guide/de/plus7"; self.jsonLink = "https://api.arte.tv/api/player/v1/config/de/%s" - + self.serachLink = self.rootLink+"/guide/de/search?q=%s&scope=plus7&kind=plus7" self.menuTree = ( TreeNode("0","Arte+7","mainPage",True), TreeNode("1","Sendungen von A-Z","showCluster",True), @@ -79,14 +77,25 @@ class ARTEMediathek(Mediathek): "ExpiringVideos":re.compile(regexSourceString%"data-nextExpiringVideos"), } + self.searchContent = re.compile(regexSourceString%"data-results"); self.regex_extractVideoSources = ( re.compile(regexSourceString%"data-highlightedVideos"), re.compile(regexSourceString%"data-latestVideos"), re.compile(regexSourceString%"data-categoryVideoSet"), + re.compile(regexSourceString%"data-videoSet") ); - - + def searchVideo(self, searchText): + link = self.serachLink%searchText; + pageContent = self.loadPage(link).decode('UTF-8'); + content = self.searchContent.search(pageContent).group(1); + content = BeautifulSoup(content); + jsonContent = json.loads(content.prettify(formatter=None)); + linkCount = len(jsonContent["programs"]); + for jsonObject in jsonContent["programs"]: + link = self.jsonLink%jsonObject["id"]; + jsonPage = json.loads(self.loadPage(link)); + self.extractVideoLinksFromJSONPage(jsonPage["videoJsonPlayer"],linkCount) def buildPageMenu(self, link, initCount): if(link == "showCluster"): @@ -109,17 +118,16 @@ class ARTEMediathek(Mediathek): jsonObject = jsonContent; else: jsonObject=self.walkJson(path,jsonContent); - self.gui.log(json.dumps(jsonObject)); if("videos" in jsonObject): self.extractVideoLinksFromJson(jsonObject); if(isinstance(jsonObject,list)): - for counter,jsonObject in enumerate(jsonObject): + for jsonObject in jsonObject: if("day" in jsonObject): - self.gui.buildJsonLink(self,jsonObject["day"],"%d"%counter,callhash,0) + name = jsonObject["day"]; + link = jsonObject["collection_url"]; + self.gui.buildVideoLink(DisplayObject(name,"","","",link,False,None),self,0); - def buildJsonLink(self,name,content): - content = BeautifulSoup(content); - jsonContent = json.loads(content.prettify(formatter=None)) + def buildJsonLink(self,name,jsonContent): callhash = self.gui.storeJsonFile(jsonContent,name); self.gui.buildJsonLink(self,name,"init",callhash,0) @@ -130,7 +138,13 @@ class ARTEMediathek(Mediathek): for name,regex in self.categories.iteritems(): match = regex.search(pageContent); if(match is not None): - self.buildJsonLink(name,match.group(1)); + content = BeautifulSoup(match.group(1)); + jsonContent = json.loads(content.prettify(formatter=None)) + if(isinstance(jsonContent,list)): + self.buildJsonLink(name,jsonContent) + elif("collection_url" in jsonContent): + link = jsonContent["collection_url"]; + self.gui.buildVideoLink(DisplayObject(name,"","","",link,False,None),self,0); self.extractVideoLinksFromHtml(pageContent) @@ -141,6 +155,7 @@ class ARTEMediathek(Mediathek): if(match is not None): someMatch = True; content = BeautifulSoup(match.group(1)); + self.gui.log(content.prettify(formatter=None)); jsonContent = json.loads(content.prettify(formatter=None)) self.extractVideoLinksFromJson(jsonContent) return someMatch; @@ -165,7 +180,7 @@ class ARTEMediathek(Mediathek): jsonCategorie = jsonObject["category"] title = unicode(jsonCategorie["title"]); link=jsonCategorie["url"]; - self.gui.buildVideoLink(DisplayObject(title,"","","",link,False,None),self,0); + self.gui.buildVideoLink(DisplayObject(title,"","","",link,False),self,0); def buildMenuEntry(self, menuItem): title = menuItem["title"]; @@ -174,15 +189,21 @@ class ARTEMediathek(Mediathek): self.gui.buildVideoLink(DisplayObject(title,subTitle,"","",link,False,None),self,0); def buildVideoEntry(self, jsonObject): - title = jsonObject["title"]; - subTitle = jsonObject["subtitle"]; - detail = jsonObject["teaser"]; + self.gui.log(json.dumps(jsonObject)); + title = unicode(jsonObject["title"]); + if(jsonObject["subtitle"] is not None): + subTitle = unicode(jsonObject["subtitle"]); + else: + subTitle = None; + detail = unicode(jsonObject["teaser"]); picture = None; for pictureItem in jsonObject["thumbnails"]: if(picture is None or picture["width"]<pictureItem["width"]): picture = pictureItem; link=self.jsonLink%jsonObject["id"]; - self.gui.buildVideoLink(DisplayObject(title,"",picture["url"],detail,link,"JsonLink", None),self,0); + pubDate = time.strptime(jsonObject["scheduled_on"],"%Y-%m-%d"); + duration = jsonObject["duration"] + self.gui.buildVideoLink(DisplayObject(title,subTitle,picture["url"],detail,link,"JsonLink", pubDate,duration),self,0); def playVideoFromJsonLink(self,link): @@ -199,16 +220,18 @@ class ARTEMediathek(Mediathek): return links; for videoObject in jsonObject["VSR"].itervalues(): + if( videoObject["versionShortLibelle"] != "DE"): + continue; if videoObject["mediaType"] == "mp4": url = videoObject["url"]; quality = videoObject["quality"]; self.gui.log("%s %s"%(quality,url)) if quality == "MQ": - links[0] = SimpleLink(url, -1); + links[0] = SimpleLink(url, -1); if quality == "HQ": - links[1] = SimpleLink(url, -1); + links[1] = SimpleLink(url, -1); if quality == "EQ": - links[2] = SimpleLink(url, -1); + links[2] = SimpleLink(url, -1); if quality == "SQ": links[3] = SimpleLink(url, -1); return links; @@ -246,7 +269,6 @@ class ARTEMediathek(Mediathek): self.extractVideoLinksFromJSONPage(jsonPage["videoJsonPlayer"],linkCount) def extractVideoLinksFromJSONPage(self, jsonPage, linkCount): - videoLinks = self.extractLinks (jsonPage); if(len(videoLinks) == 0): return; @@ -258,5 +280,16 @@ class ARTEMediathek(Mediathek): if("subtitle" in jsonPage): subTitle = jsonPage["subtitle"]; + detail = ""; + if("V7T" in jsonPage): + detail = self.gui.transformHtmlCodes(jsonPage["V7T"]); - self.gui.buildVideoLink(DisplayObject(title,subTitle,picture,"",videoLinks,True, None),self,linkCount); + duration = None; + if("videoDurationSeconds" in jsonPage): + duration = jsonPage["videoDurationSeconds"]; + + if("VRA" in jsonPage): + pubDate = time.strptime(jsonPage["VRA"],"%d/%m/%Y %H:%M:%S +0000"); + else: + pubDate = time.gmtime(); + self.gui.buildVideoLink(DisplayObject(title,subTitle,picture,detail,videoLinks,True, pubDate, duration),self,linkCount); diff --git a/plugin.video.mediathek/mediathek/zdf.py b/plugin.video.mediathek/mediathek/zdf.py index 3ece7a9..5a794c8 100644 --- a/plugin.video.mediathek/mediathek/zdf.py +++ b/plugin.video.mediathek/mediathek/zdf.py @@ -15,7 +15,7 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. -import re,math,traceback,time +import re,traceback,time from mediathek import * from datetime import datetime,timedelta import json @@ -87,9 +87,9 @@ class ZDFMediathek(Mediathek): if entry["type"] == "brand": categoriePages.append(entry); if entry["type"] == "video": - videoObjects.append(entry); + videoObjects.append(entry); self.gui.log("CategoriePages: %d"%len(categoriePages)); - self.gui.log("VideoPages: %d"%len(videoObjects)); + self.gui.log("VideoPages: %d"%len(videoObjects)); for categoriePage in categoriePages: title=categoriePage["titel"]; subTitle=categoriePage["beschreibung"]; @@ -117,12 +117,16 @@ class ZDFMediathek(Mediathek): for width,imageObject in videoObject["teaserBild"].iteritems(): if int(width)<=840: imageLink=imageObject["url"]; + if("visibleFrom" in videoObject): + date = time.strptime(videoObject["visibleFrom"],"%d.%m.%Y %H:%M"); + else: + date = time.gmtime(); if("formitaeten" in videoObject): links = self.extractLinks(videoObject); - self.gui.buildVideoLink(DisplayObject(title,subTitle,imageLink,description,links,True,None,videoObject.get('length')),self,counter); + self.gui.buildVideoLink(DisplayObject(title,subTitle,imageLink,description,links,True,date,videoObject.get('length')),self,counter); else: link = videoObject["url"]; - self.gui.buildVideoLink(DisplayObject(title,subTitle,imageLink,description,link,"JsonLink",None,videoObject.get('length')),self,counter); + self.gui.buildVideoLink(DisplayObject(title,subTitle,imageLink,description,link,"JsonLink",date,videoObject.get('length')),self,counter); def playVideoFromJsonLink(self,link): jsonObject = json.loads(self.loadPage(link)); @@ -139,11 +143,11 @@ class ZDFMediathek(Mediathek): links[4] = SimpleLink(url, -1); else: if quality == "low": - links[0] = SimpleLink(url, -1); + links[0] = SimpleLink(url, -1); if quality == "med": - links[1] = SimpleLink(url, -1); + links[1] = SimpleLink(url, -1); if quality == "high": - links[2] = SimpleLink(url, -1); + links[2] = SimpleLink(url, -1); if quality == "veryhigh": links[3] = SimpleLink(url, -1); if quality == "auto": diff --git a/plugin.video.mediathek/simplexbmc.py b/plugin.video.mediathek/simplexbmc.py index 8924b34..e55d0d8 100644 --- a/plugin.video.mediathek/simplexbmc.py +++ b/plugin.video.mediathek/simplexbmc.py @@ -14,7 +14,7 @@ # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. +# along with this program. If not, see <http://www.gnu.org/licenses/>. import xbmc, xbmcgui, xbmcplugin,xbmcaddon, sys, urllib, os, time, re from bs4 import BeautifulSoup; import json @@ -45,60 +45,58 @@ class SimpleXbmcGui(object): xbmc.log("[%s]: %s" % (__plugin__, msg.encode('utf8'))) def buildVideoLink(self, displayObject, mediathek, objectCount): - if(displayObject.subTitle == "" or displayObject.subTitle == displayObject.title): - title = self.transformHtmlCodes(displayObject.title); - else: - title = self.transformHtmlCodes(displayObject.title +" - "+ displayObject.subTitle); - if displayObject.date is not None: - title = "(%s) %s"%(time.strftime("%d.%m",displayObject.date),title); + metaData = self.BuildMeteData(displayObject) if displayObject.picture is not None: - listItem=xbmcgui.ListItem(title, iconImage="DefaultFolder.png", thumbnailImage=displayObject.picture) + listItem=xbmcgui.ListItem(metaData["title"], iconImage="DefaultFolder.png", thumbnailImage=displayObject.picture) else: - listItem=xbmcgui.ListItem(title, iconImage="DefaultFolder.png") + listItem=xbmcgui.ListItem(metaData["title"], iconImage="DefaultFolder.png") + listItem.setInfo("video",metaData); + if(displayObject.isPlayable): if(displayObject.isPlayable == "PlayList"): link = displayObject.link[0] url = "%s?type=%s&action=openPlayList&link=%s" % (sys.argv[0],mediathek.name(), urllib.quote_plus(link.basePath)) listItem.setProperty('IsPlayable', 'true'); - xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]),url=url,listitem=listItem,isFolder=False,totalItems = objectCount) + xbmcplugin.addDirectoryItem(int(sys.argv[1]),url,listItem,False,objectCount) elif(displayObject.isPlayable == "JsonLink"): link = displayObject.link url = "%s?type=%s&action=openJsonLink&link=%s" % (sys.argv[0],mediathek.name(), urllib.quote_plus(link)) listItem.setProperty('IsPlayable', 'true'); - listItem.setInfo("video", { - "mediatype":"video", - "title": title, - "plot": self.transformHtmlCodes(displayObject.description), - "duration": displayObject.duration - }) - xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]),url=url,listitem=listItem,isFolder=False,totalItems = objectCount) + xbmcplugin.addDirectoryItem(int(sys.argv[1]),url,listItem, False, objectCount) else: - self.log(displayObject.title); link = self.extractLink(displayObject.link); if(isinstance(link,ComplexLink)): self.log("PlayPath:"+ link.playPath); listItem.setProperty("PlayPath", link.playPath); + listItem.setProperty('IsPlayable', 'true'); + xbmcplugin.addDirectoryItem(int(sys.argv[1]),link.basePath,listItem,False,objectCount) + else: + url = "%s?type=%s&action=openTopicPage&link=%s" % (sys.argv[0],mediathek.name(), urllib.quote_plus(displayObject.link)) + xbmcplugin.addDirectoryItem(int(sys.argv[1]),url,listItem,True,objectCount) + + def BuildMeteData(self, displayObject): + if(displayObject.subTitle is None or displayObject.subTitle == "" or displayObject.subTitle == displayObject.title): + title = self.transformHtmlCodes(displayObject.title.rstrip()); + else: + title = self.transformHtmlCodes(displayObject.title.rstrip() +" - "+ displayObject.subTitle.rstrip()); + if displayObject.date is not None: + title = "(%s) %s"%(time.strftime("%d.%m",displayObject.date),title.rstrip()); - self.log("URL:"+ link.basePath); + metaData = { + "mediatype":"video", + "title": title, + "plotoutline": self.transformHtmlCodes(displayObject.description) + } - metaData = { - "mediatype":"video", - "size": link.size, - "title": title, - "plot": self.transformHtmlCodes(displayObject.description), - "duration": displayObject.duration - } + if(displayObject.duration is not None): + metaData["duration"] = int(displayObject.duration); - if(displayObject.date is not None): + if(displayObject.date is not None): + self.log(time.strftime("%d.%m.%Y",displayObject.date)); + self.log(time.strftime("%Y",displayObject.date)); metaData["date"] =time.strftime("%d.%m.%Y",displayObject.date); metaData["year"] =int(time.strftime("%Y",displayObject.date)); - - listItem.setInfo("video",metaData); - listItem.setProperty('IsPlayable', 'true'); - xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]),url=link.basePath,listitem=listItem,isFolder=False,totalItems = objectCount) - else: - url = "%s?type=%s&action=openTopicPage&link=%s" % (sys.argv[0],mediathek.name(), urllib.quote_plus(displayObject.link)) - xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]),url=url,listitem=listItem,isFolder=True,totalItems = objectCount) + return metaData; def transformHtmlCodes(self, content): return BeautifulSoup(content).prettify(formatter=None); @@ -119,7 +117,7 @@ class SimpleXbmcGui(object): with open(storedJsonFile, 'wb') as output: json.dump(jsonObject,output); return callhash; - + def loadJsonFile(self,callhash): storedJsonFile = os.path.join(self.plugin_profile_dir,"%s.json"%callhash); with open(storedJsonFile,"rb") as input: |