# -*- 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 ("Unser Player ist in der Beta-Phase. Klicke hier, um den alten Player zu benutzen" in html) or ("Changer de lecteur" in html) or ("Our player is in beta, click here to go back to the old one" 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))