# -*- coding: utf-8 -*- # Watchbox # Copyright (C) 2017 MrKrabat # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as # published by the Free Software Foundation, either version 3 of the # License, or (at your option) any later version. # # This program 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 Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . import re import sys import json import urllib import urllib2 from bs4 import BeautifulSoup import xbmc import xbmcgui import xbmcplugin import login import view def genres_show(args): """Show all genres """ response = urllib2.urlopen("https://www.watchbox.de/genres/") html = response.read() soup = BeautifulSoup(html, "html.parser") div = soup.find("div", {"class": "grid_genres_b"}) for item in div.find_all("section"): view.add_item(args, {"url": item.a["href"], "title": item.find("div", {"class": "text_browse-teaser-title"}).string.strip().encode("utf-8"), "mode": "genre_list", "genre": item.find("div", {"class": "text_browse-teaser-title"}).string.strip().encode("utf-8"), "plot": item.find("div", {"class": "text_browse-teaser-subtitle"}).string.strip().encode("utf-8")}, isFolder=True, mediatype="video") view.endofdirectory() def genre_list(args): """List options for gernre """ view.add_item(args, {"title": args._addon.getLocalizedString(30022), "url": args.url, "mode": "genre_all"}) view.add_item(args, {"title": args._addon.getLocalizedString(30023), "url": args.url, "mode": "genre_movie"}) view.add_item(args, {"title": args._addon.getLocalizedString(30024), "url": args.url, "mode": "genre_tvshows"}) view.add_item(args, {"title": args._addon.getLocalizedString(30030), "url": args.url, "mode": "genre_all"}) view.add_item(args, {"title": args._addon.getLocalizedString(30031), "url": args.url, "mode": "genre_new"}) view.endofdirectory() def genre_view(mode, args): """Show all tv shows / movies """ url = "" if hasattr(args, "offset"): url = "?page=" + str(args.offset) if mode == 1: response = urllib2.urlopen("https://www.watchbox.de" + args.url + "filme/" + url) elif mode == 2: response = urllib2.urlopen("https://www.watchbox.de" + args.url + "serien/" + url) elif mode == 3: response = urllib2.urlopen("https://www.watchbox.de/beste/" + url) elif mode == 4: response = urllib2.urlopen("https://www.watchbox.de/neu/" + url) elif mode == 5: response = urllib2.urlopen("https://www.watchbox.de" + args.url + "neu/" + url) else: response = urllib2.urlopen("https://www.watchbox.de" + args.url + "beste/" + url) html = response.read() soup = BeautifulSoup(html, "html.parser") div = soup.find("div", {"class": "teaser-pagination__page"}) for item in div.find_all("section"): try: meta = item.find("div", {"class": "text_teaser-portrait-meta"}).string.strip().encode("utf-8") duration, country, year, fsk = meta.split("|") duration = duration.strip()[:-5] duration = str(int(duration) * 60) year = year.strip() except TypeError: duration = "" year = "" thumb = item.img["src"].replace(" ", "%20") if thumb[:4] != "http": thumb = "https:" + thumb if (mode == 1) or (".html" in item.a["href"]): view.add_item(args, {"url": item.a["href"], "title": item.find("div", {"class": "text_teaser-portrait-title"}).string.strip().encode("utf-8"), "mode": "videoplay", "thumb": thumb, "fanart": thumb, "year": year, "duration": duration, "plot": item.find("div", {"class": "text_teaser-portrait-description"}).string.strip().encode("utf-8")}, isFolder=False, mediatype="video") else: view.add_item(args, {"url": item.a["href"], "title": item.find("div", {"class": "text_teaser-portrait-title"}).string.strip().encode("utf-8"), "mode": "season_list", "thumb": thumb, "fanart": thumb, "year": year, "duration": duration, "plot": item.find("div", {"class": "text_teaser-portrait-description"}).string.strip().encode("utf-8")}, isFolder=True, mediatype="video") if "Zeig mir mehr" in html: view.add_item(args, {"title": args._addon.getLocalizedString(30025).encode("utf-8"), "url": getattr(args, "url", ""), "offset": str(int(getattr(args, "offset", 0)) + 1), "mode": args.mode}) view.endofdirectory() def mylist(args): """Show my list """ response = urllib2.urlopen("https://www.watchbox.de/meine-liste") html = response.read() soup = BeautifulSoup(html, "html.parser") div = soup.find("div", {"class": "grid"}) for item in div.find_all("section"): try: meta = item.find("div", {"class": "text_teaser-portrait-meta"}).string.strip().encode("utf-8") country, year, fsk = meta.split("|") year = year.strip() except TypeError: year = "" thumb = item.img["src"].replace(" ", "%20") if thumb[:4] != "http": thumb = "https:" + thumb if ".html" in item.a["href"]: view.add_item(args, {"url": item.a["href"], "title": item.find("div", {"class": "text_teaser-portrait-title"}).string.strip().encode("utf-8"), "mode": "videoplay", "thumb": thumb, "fanart": thumb, "year": year, "plot": item.find("div", {"class": "text_teaser-portrait-description"}).string.strip().encode("utf-8")}, isFolder=False, mediatype="video") else: view.add_item(args, {"url": item.a["href"], "title": item.find("div", {"class": "text_teaser-portrait-title"}).string.strip().encode("utf-8"), "mode": "season_list", "thumb": thumb, "fanart": thumb, "year": year, "plot": item.find("div", {"class": "text_teaser-portrait-description"}).string.strip().encode("utf-8")}, isFolder=True, mediatype="video") view.endofdirectory() def season_list(args): """Show all seasons """ response = urllib2.urlopen("https://www.watchbox.de" + args.url) html = response.read() soup = BeautifulSoup(html, "html.parser") ul = soup.find("ul", {"class": "season-panel"}) if not ul: view.endofdirectory() return try: plot = soup.find("p", {"class": "more-text"}) plot.span.decompose() except AttributeError: pass for item in ul.find_all("li"): view.add_item(args, {"url": item.a["href"], "title": item.a.string.strip().encode("utf-8"), "thumb": args.thumb, "fanart": args.fanart, "plot": plot.get_text().strip().encode("utf-8"), "plotoutline": args.plot, "mode": "episode_list"}, isFolder=True, mediatype="video") view.endofdirectory() def episode_list(args): """Show all episodes """ response = urllib2.urlopen("https://www.watchbox.de" + args.url) html = response.read() soup = BeautifulSoup(html, "html.parser") div = soup.find("div", {"class": "swiper-wrapper"}) if not div: view.endofdirectory() return for item in div.find_all("section"): episode = item.find("div", {"class": "teaser__season-info"}).string.strip().encode("utf-8") matches = re.findall(r"([0-9]{1,3})", episode) thumb = item.img["data-src"].replace(" ", "%20") if thumb[:4] != "http": thumb = "https:" + thumb if not len(matches) == 2: view.add_item(args, {"url": item.a["href"], "title": item.find("div", {"class": "text_teaser-landscape-title"}).string.strip().encode("utf-8"), "thumb": thumb, "fanart": args.fanart, "duration": getattr(args, "duration", ""), "mode": "videoplay"}, isFolder=False, mediatype="video") else: view.add_item(args, {"url": item.a["href"], "title": matches[1] + " - " + item.find("div", {"class": "text_teaser-landscape-title"}).string.strip().encode("utf-8"), "thumb": thumb, "fanart": args.fanart, "episode": matches[1], "season": matches[0], "duration": getattr(args, "duration", ""), "mode": "videoplay"}, isFolder=False, mediatype="video") view.endofdirectory() def search(args): """Search function """ d = xbmcgui.Dialog().input(args._addon.getLocalizedString(30021), type=xbmcgui.INPUT_ALPHANUM) if not d or len(d) < 2: return response = urllib2.urlopen("https://api.watchbox.de/v1/search/?page=1&maxPerPage=28&active=true&term=" + urllib.quote_plus(d)) html = response.read() # parse json json_obj = json.loads(html) for item in json_obj["items"]: if str(item["type"]) == "film": view.add_item(args, {"url": "/serien/test-" + str(item["entityId"]) + "/", "title": item["headline"].encode("utf-8"), "mode": "videoplay", "thumb": "https://aiswatchbox-a.akamaihd.net/watchbox/format/" + str(item["entityId"]) + "_dvdcover/600x840/test.jpg", "fanart": "https://aiswatchbox-a.akamaihd.net/watchbox/format/" + str(item["entityId"]) + "_dvdcover/600x840/test.jpg", "year": item["productionYear"].encode("utf-8"), "genre": item["genres"][0].encode("utf-8"), "plot": item["description"].encode("utf-8"), "plotoutline": item["infoTextShort"].encode("utf-8")}, isFolder=False, mediatype="video") else: view.add_item(args, {"url": "/serien/test-" + str(item["entityId"]) + "/", "title": item["headline"].encode("utf-8"), "mode": "season_list", "thumb": "https://aiswatchbox-a.akamaihd.net/watchbox/format/" + str(item["entityId"]) + "_dvdcover/600x840/test.jpg", "fanart": "https://aiswatchbox-a.akamaihd.net/watchbox/format/" + str(item["entityId"]) + "_dvdcover/600x840/test.jpg", "year": item["productionYear"].encode("utf-8"), "genre": item["genres"][0].encode("utf-8"), "plot": item["description"].encode("utf-8"), "plotoutline": item["infoTextShort"].encode("utf-8")}, isFolder=True, mediatype="video") view.endofdirectory() def startplayback(args): """Plays a video """ response = urllib2.urlopen("https://www.watchbox.de" + args.url) html = response.read() regex = r"hls\: '(.*?)'," matches = re.search(regex, html).group(1) if matches: # play stream item = xbmcgui.ListItem(getattr(args, "title", "Title not provided"), path=matches + login.getCookie(args)) item.setMimeType("application/vnd.apple.mpegurl") item.setContentLookup(False) xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, item) else: xbmc.log("[PLUGIN] %s: Failed to play stream" % args._addonname, xbmc.LOGERROR) xbmcgui.Dialog().ok(args._addonname, args._addon.getLocalizedString(30044))