# -*- coding: utf-8 -*- # Wakanim - Watch videos from the german anime platform Wakanim.tv on Kodi. # 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 urllib import urllib2 from bs4 import BeautifulSoup import xbmc import xbmcgui import xbmcplugin import login import view def showCatalog(args): """Show all animes """ response = urllib2.urlopen("https://www.wakanim.tv/" + args._country + "/v2/catalogue") html = response.read() soup = BeautifulSoup(html, "html.parser") ul = soup.find("ul", {"class": "catalog_list"}) for li in ul.find_all("li"): plot = li.find("p", {"class": "tooltip_text"}) stars = li.find("div", {"class": "stars"}) star = stars.find_all("span", {"class": "-no"}) thumb = li.img["src"].replace(" ", "%20") if thumb[:4] != "http": thumb = "https:" + thumb view.add_item(args, {"url": li.a["href"], "title": li.find("div", {"class": "slider_item_description"}).span.strong.string.strip().encode("utf-8"), "tvshowtitle": li.find("div", {"class": "slider_item_description"}).span.strong.string.strip().encode("utf-8"), "mode": "list_season", "thumb": thumb, "fanart": thumb, "rating": str(10 - len(star) * 2), "plot": plot.contents[3].string.strip().encode("utf-8"), "year": li.time.string.strip().encode("utf-8")}, isFolder=True, mediatype="video") view.endofdirectory() def searchAnime(args): """Search for animes """ d = xbmcgui.Dialog().input(args._addon.getLocalizedString(30021), type=xbmcgui.INPUT_ALPHANUM) if not d: return post_data = urllib.urlencode({"search": d}) response = urllib2.urlopen("https://www.wakanim.tv/" + args._country + "/v2/catalogue/search", post_data) html = response.read() soup = BeautifulSoup(html, "html.parser") ul = soup.find("ul", {"class": "catalog_list"}) if not ul: view.endofdirectory() return for li in ul.find_all("li"): plot = li.find("p", {"class": "tooltip_text"}) stars = li.find("div", {"class": "stars"}) star = stars.find_all("span", {"class": "-no"}) thumb = li.img["src"].replace(" ", "%20") if thumb[:4] != "http": thumb = "https:" + thumb view.add_item(args, {"url": li.a["href"], "title": li.find("div", {"class": "slider_item_description"}).span.strong.string.strip().encode("utf-8"), "mode": "list_season", "thumb": thumb, "fanart": thumb, "rating": str(10 - len(star) * 2), "plot": plot.contents[3].string.strip().encode("utf-8"), "year": li.time.string.strip().encode("utf-8")}, isFolder=True, mediatype="video") view.endofdirectory() def myDownloads(args): """View download able animes May not every episode is download able. """ response = urllib2.urlopen("https://www.wakanim.tv/" + args._country + "/v2/mydownloads") html = response.read() soup = BeautifulSoup(html, "html.parser") container = soup.find("div", {"class": "big-item-list"}) if not container: view.endofdirectory() return for div in container.find_all("div", {"class": "big-item-list_item"}): thumb = div.img["src"].replace(" ", "%20") if thumb[:4] != "http": thumb = "https:" + thumb view.add_item(args, {"url": div.a["href"].replace("mydownloads/detail", "catalogue/show"), "title": div.find("h3", {"class": "big-item_title"}).string.strip().encode("utf-8"), "mode": "list_season", "thumb": thumb, "fanart": thumb}, isFolder=True, mediatype="video") view.endofdirectory() def myCollection(args): """View collection """ response = urllib2.urlopen("https://www.wakanim.tv/" + args._country + "/v2/collection") html = response.read() soup = BeautifulSoup(html, "html.parser") container = soup.find("div", {"class": "big-item-list"}) if not container: view.endofdirectory() return for div in container.find_all("div", {"class": "big-item-list_item"}): thumb = div.img["src"].replace(" ", "%20") if thumb[:4] != "http": thumb = "https:" + thumb view.add_item(args, {"url": div.a["href"].replace("collection/detail", "catalogue/show"), "title": div.find("h3", {"class": "big-item_title"}).string.strip().encode("utf-8"), "mode": "list_season", "thumb": thumb, "fanart": thumb}, isFolder=True, mediatype="video") view.endofdirectory() def listSeason(args): """Show all seasons/arcs of an anime """ response = urllib2.urlopen("https://www.wakanim.tv" + args.url) html = response.read() soup = BeautifulSoup(html, "html.parser") date = soup.find_all("span", {"class": "border-list_text"})[0].find_all("span") year = date[2].string.strip().encode("utf-8") date = year + "-" + date[1].string.strip().encode("utf-8") + "-" + date[0].string.strip().encode("utf-8") originaltitle = soup.find_all("span", {"class": "border-list_text"})[1].string.strip().encode("utf-8") plot = soup.find("div", {"class": "serie_description"}).string.strip().encode("utf-8") credits = soup.find("div", {"class": "serie_description_more"}).p.string.strip().encode("utf-8") trailer = soup.find("div", {"class": "TrailerEp-iframeWrapperRatio"}) try: trailer = trailer.iframe["src"] trailer = "plugin://plugin.video.youtube/play/?video_id=" + re.search(r"(?:\.be/|/embed)/?([^&=%:/\?]{11})", trailer).group(1) view.add_item(args, {"url": trailer, "mode": "trailer", "thumb": args.thumb.replace(" ", "%20"), "fanart": args.fanart.replace(" ", "%20"), "title": args._addon.getLocalizedString(30024)}, isFolder=False, mediatype="video") except AttributeError: trailer = "" for section in soup.find_all("h2", {"class": "slider-section_title"}): if not section.span: continue title = section.get_text()[6:].strip() view.add_item(args, {"url": args.url, "title": title.encode("utf-8"), "mode": "list_episodes", "thumb": args.thumb.replace(" ", "%20"), "fanart": args.fanart.replace(" ", "%20"), "season": title.encode("utf-8"), "plot": plot, "plotoutline": getattr(args, "plot", ""), "year": year, "premiered": date, "trailer": trailer, "originaltitle": originaltitle, "credits": credits}, isFolder=True, mediatype="video") view.endofdirectory() def listEpisodes(args): """Show all episodes of an season/arc """ response = urllib2.urlopen("https://www.wakanim.tv" + args.url) html = response.read() soup = BeautifulSoup(html, "html.parser") for season in soup.findAll(text=args.title): parent = season.find_parent("li") if not parent: continue thumb = parent.img["src"].replace(" ", "%20") if thumb[:4] != "http": thumb = "https:" + thumb view.add_item(args, {"url": parent.a["href"], "title": parent.img["alt"].encode("utf-8"), "mode": "videoplay", "thumb": args.thumb.replace(" ", "%20"), "fanart": args.fanart.replace(" ", "%20")}, isFolder=False, mediatype="video") view.endofdirectory() def startplayback(args): """Plays a video """ response = urllib2.urlopen("https://www.wakanim.tv" + args.url) html = response.read() soup = BeautifulSoup(html, "html.parser") # check if not premium if ("Diese Folge ist für Abonnenten reserviert" in html) or ("Cet épisode est reservé à nos abonnés" in html) or ("This episode is reserved for our subscribers" in html): xbmc.log("[PLUGIN] %s: You need to own this video or be a premium member '%s'" % (args._addonname, args.url), xbmc.LOGERROR) xbmcgui.Dialog().ok(args._addonname, args._addon.getLocalizedString(30043)) return # check if we have to reactivate video if "reactivate" in html: # reactivate video a = soup.find("div", {"id": "jwplayer-container"}).a["href"] response = urllib2.urlopen("https://www.wakanim.tv" + a) html = response.read() # reload page response = urllib2.urlopen("https://www.wakanim.tv" + args.url) html = response.read() soup = BeautifulSoup(html, "html.parser") # check if successfull if "reactivate" in html: xbmc.log("[PLUGIN] %s: Reactivation failed '%s'" % (args._addonname, args.url), xbmc.LOGERROR) xbmcgui.Dialog().ok(args._addonname, args._addon.getLocalizedString(30042)) return # using stream with hls+aes if ("Benutzer wechseln" in html) or ("Changer de lecteur" in html) or ("Change user" in html): # streaming is only for premium subscription if (("Kostenlos" in html) or ("Gratuit" in html) or ("Free" in html)) and not ("episode_premium_title" in html): xbmc.log("[PLUGIN] %s: You need to own this video or be a premium member '%s'" % (args._addonname, args.url), xbmc.LOGERROR) xbmcgui.Dialog().ok(args._addonname, args._addon.getLocalizedString(30043)) return # get stream file regex = r"file: \"(.*?)\"," matches = re.search(regex, html).group(1) if matches: # manifest url url = "https://www.wakanim.tv" + matches # play stream item = xbmcgui.ListItem(getattr(args, "title", "Title not provided"), path=url + 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)) else: xbmc.log("[PLUGIN] %s: You need to own this video or be a premium member '%s'" % (args._addonname, args.url), xbmc.LOGERROR) xbmcgui.Dialog().ok(args._addonname, args._addon.getLocalizedString(30043))