summaryrefslogtreecommitdiff
path: root/plugin.video.wakanim/resources
diff options
context:
space:
mode:
authorMrKrabat <MrKrabat@users.noreply.github.com>2017-10-07 01:20:59 +0200
committerlearningit <scottyroscoe13@gmail.com>2017-10-06 19:20:59 -0400
commit8d0c63c851e9f35a6cd283c7fb186727feaf649b (patch)
treed27cf558652e1bea02c2a47ac3a94e1410599650 /plugin.video.wakanim/resources
parent8388e6878216741b9e5c6d17e509a2d173cec915 (diff)
[plugin.video.wakanim] 0.3.0 (#1444)
Diffstat (limited to 'plugin.video.wakanim/resources')
-rw-r--r--plugin.video.wakanim/resources/__init__.py1
-rw-r--r--plugin.video.wakanim/resources/language/resource.language.de_de/strings.po99
-rw-r--r--plugin.video.wakanim/resources/language/resource.language.en_gb/strings.po99
-rw-r--r--plugin.video.wakanim/resources/language/resource.language.fr_fr/strings.po99
-rw-r--r--plugin.video.wakanim/resources/lib/__init__.py1
-rw-r--r--plugin.video.wakanim/resources/lib/cmdargs.py59
-rw-r--r--plugin.video.wakanim/resources/lib/login.py94
-rw-r--r--plugin.video.wakanim/resources/lib/netapi.py300
-rw-r--r--plugin.video.wakanim/resources/lib/view.py137
-rw-r--r--plugin.video.wakanim/resources/lib/wakanim.py124
-rw-r--r--plugin.video.wakanim/resources/settings.xml9
11 files changed, 1022 insertions, 0 deletions
diff --git a/plugin.video.wakanim/resources/__init__.py b/plugin.video.wakanim/resources/__init__.py
new file mode 100644
index 0000000..b93054b
--- /dev/null
+++ b/plugin.video.wakanim/resources/__init__.py
@@ -0,0 +1 @@
+# Dummy file to make this directory a package.
diff --git a/plugin.video.wakanim/resources/language/resource.language.de_de/strings.po b/plugin.video.wakanim/resources/language/resource.language.de_de/strings.po
new file mode 100644
index 0000000..98aab0a
--- /dev/null
+++ b/plugin.video.wakanim/resources/language/resource.language.de_de/strings.po
@@ -0,0 +1,99 @@
+# Kodi Media Center language file
+msgid ""
+msgstr ""
+"Project-Id-Version: Kodi Addons\n"
+"Report-Msgid-Bugs-To: alanwww1@kodi.org\n"
+"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: de\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+
+# Wakanim Settings
+
+msgctxt "#30001"
+msgid "Username"
+msgstr "Benutzername"
+
+msgctxt "#30002"
+msgid "Password"
+msgstr "Passwort"
+
+msgctxt "#30003"
+msgid "Video quality"
+msgstr "Video Qualität"
+
+msgctxt "#30004"
+msgid "720p (HD)"
+msgstr "720p (HD)"
+
+msgctxt "#30005"
+msgid "1080p (FullHD)"
+msgstr "1080p (FullHD)"
+
+msgctxt "#30006"
+msgid "1440p (QHD 2K)"
+msgstr "1440p (QHD 2K)"
+
+msgctxt "#30007"
+msgid "2160p (UDH 4K)"
+msgstr "2160p (UDH 4K)"
+
+msgctxt "#30010"
+msgid "Region"
+msgstr "Region"
+
+msgctxt "#30011"
+msgid "Germany"
+msgstr "Deutschland"
+
+msgctxt "#30012"
+msgid "France, Belgium, Switzerland, Quebec"
+msgstr "Frankreich, Belgien, Schweiz, Quebec"
+
+msgctxt "#30013"
+msgid "Sweden, Norway, Iceland, Finland, Denmark"
+msgstr "Schweden, Norwegen, Island, Finnland, Dänemark"
+
+
+# Wakanim Menue
+
+msgctxt "#30020"
+msgid "Catalog"
+msgstr "Katalog"
+
+msgctxt "#30021"
+msgid "Search"
+msgstr "Suchen"
+
+msgctxt "#30022"
+msgid "My downloads"
+msgstr "Meine Downloads"
+
+msgctxt "#30023"
+msgid "My collection"
+msgstr "Meine Sammlung"
+
+
+# Wakanim Messages
+
+msgctxt "#30040"
+msgid "Login failed"
+msgstr "Login fehlgeschlagen"
+
+msgctxt "#30041"
+msgid "An error occurred"
+msgstr "Ein Fehler ist aufgetreten"
+
+msgctxt "#30043"
+msgid "You need to be premium or own this video"
+msgstr "Du musst premium nutzer sein oder das Video gekauft haben"
+
+msgctxt "#30044"
+msgid "Failed to play video or stream"
+msgstr "Fehlgeschlagen das Video oder den Stream abzuspielen"
diff --git a/plugin.video.wakanim/resources/language/resource.language.en_gb/strings.po b/plugin.video.wakanim/resources/language/resource.language.en_gb/strings.po
new file mode 100644
index 0000000..89aae68
--- /dev/null
+++ b/plugin.video.wakanim/resources/language/resource.language.en_gb/strings.po
@@ -0,0 +1,99 @@
+# Kodi Media Center language file
+msgid ""
+msgstr ""
+"Project-Id-Version: Kodi Addons\n"
+"Report-Msgid-Bugs-To: alanwww1@kodi.org\n"
+"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: en\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+
+# Wakanim Settings
+
+msgctxt "#30001"
+msgid "Username"
+msgstr ""
+
+msgctxt "#30002"
+msgid "Password"
+msgstr ""
+
+msgctxt "#30003"
+msgid "Video quality"
+msgstr ""
+
+msgctxt "#30004"
+msgid "720p (HD)"
+msgstr ""
+
+msgctxt "#30005"
+msgid "1080p (FullHD)"
+msgstr ""
+
+msgctxt "#30006"
+msgid "1440p (QHD 2K)"
+msgstr ""
+
+msgctxt "#30007"
+msgid "2160p (UDH 4K)"
+msgstr ""
+
+msgctxt "#30010"
+msgid "Region"
+msgstr ""
+
+msgctxt "#30011"
+msgid "Germany"
+msgstr ""
+
+msgctxt "#30012"
+msgid "France, Belgium, Switzerland, Quebec"
+msgstr ""
+
+msgctxt "#30013"
+msgid "Sweden, Norway, Iceland, Finland, Denmark"
+msgstr ""
+
+
+# Wakanim Menue
+
+msgctxt "#30020"
+msgid "Catalog"
+msgstr ""
+
+msgctxt "#30021"
+msgid "Search"
+msgstr ""
+
+msgctxt "#30022"
+msgid "My downloads"
+msgstr ""
+
+msgctxt "#30023"
+msgid "My collection"
+msgstr ""
+
+
+# Wakanim Messages
+
+msgctxt "#30040"
+msgid "Login failed"
+msgstr ""
+
+msgctxt "#30041"
+msgid "An error occurred"
+msgstr ""
+
+msgctxt "#30043"
+msgid "You need to be premium or own this video"
+msgstr ""
+
+msgctxt "#30044"
+msgid "Failed to play video or stream"
+msgstr ""
diff --git a/plugin.video.wakanim/resources/language/resource.language.fr_fr/strings.po b/plugin.video.wakanim/resources/language/resource.language.fr_fr/strings.po
new file mode 100644
index 0000000..15d0e24
--- /dev/null
+++ b/plugin.video.wakanim/resources/language/resource.language.fr_fr/strings.po
@@ -0,0 +1,99 @@
+# Kodi Media Center language file
+msgid ""
+msgstr ""
+"Project-Id-Version: Kodi Addons\n"
+"Report-Msgid-Bugs-To: alanwww1@kodi.org\n"
+"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: fr\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+
+# Wakanim Settings
+
+msgctxt "#30001"
+msgid "Username"
+msgstr "Utilisateur"
+
+msgctxt "#30002"
+msgid "Password"
+msgstr "Mot de passe"
+
+msgctxt "#30003"
+msgid "Video quality"
+msgstr "Qualité vidéo"
+
+msgctxt "#30004"
+msgid "720p (HD)"
+msgstr "720p (HD)"
+
+msgctxt "#30005"
+msgid "1080p (FullHD)"
+msgstr "1080p (FullHD)"
+
+msgctxt "#30006"
+msgid "1440p (QHD 2K)"
+msgstr "1440p (QHD 2K)"
+
+msgctxt "#30007"
+msgid "2160p (UDH 4K)"
+msgstr "2160p (UDH 4K)"
+
+msgctxt "#30010"
+msgid "Region"
+msgstr "Région"
+
+msgctxt "#30011"
+msgid "Germany"
+msgstr "Allemagne"
+
+msgctxt "#30012"
+msgid "France, Belgium, Switzerland, Quebec"
+msgstr "France, Belgique, Suisse, Quebec"
+
+msgctxt "#30013"
+msgid "Sweden, Norway, Iceland, Finland, Denmark"
+msgstr "Suède, Norvège, Islande, Finlande, Danemark"
+
+
+# Wakanim Menue
+
+msgctxt "#30020"
+msgid "Catalog"
+msgstr "Catalogue"
+
+msgctxt "#30021"
+msgid "Search"
+msgstr "Rechercher"
+
+msgctxt "#30022"
+msgid "My downloads"
+msgstr "Mes téléchargements"
+
+msgctxt "#30023"
+msgid "My collection"
+msgstr "Ma collection"
+
+
+# Wakanim Messages
+
+msgctxt "#30040"
+msgid "Login failed"
+msgstr "Échec de la connexion"
+
+msgctxt "#30041"
+msgid "An error occurred"
+msgstr "Une erreur s'est produite"
+
+msgctxt "#30043"
+msgid "You need to be premium or own this video"
+msgstr "Vous devez être premium ou posséder cette vidéo"
+
+msgctxt "#30044"
+msgid "Failed to play video or stream"
+msgstr "Impossible de lire de la vidéo ou du flux"
diff --git a/plugin.video.wakanim/resources/lib/__init__.py b/plugin.video.wakanim/resources/lib/__init__.py
new file mode 100644
index 0000000..b93054b
--- /dev/null
+++ b/plugin.video.wakanim/resources/lib/__init__.py
@@ -0,0 +1 @@
+# Dummy file to make this directory a package.
diff --git a/plugin.video.wakanim/resources/lib/cmdargs.py b/plugin.video.wakanim/resources/lib/cmdargs.py
new file mode 100644
index 0000000..fbd358e
--- /dev/null
+++ b/plugin.video.wakanim/resources/lib/cmdargs.py
@@ -0,0 +1,59 @@
+# -*- 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 <http://www.gnu.org/licenses/>.
+
+import sys
+import urllib
+
+
+def parse_args():
+ """Decode arguments.
+ """
+ if (sys.argv[2]):
+ return Args(**dict([p.split("=")
+ for p in sys.argv[2][1:].split("&")]))
+
+ else:
+ # Args will turn the "None" into None.
+ # Don't simply define it as None because unquote_plus in updateArgs
+ # will throw an exception.
+ # This is a pretty ugly solution.
+ return Args(mode = "None",
+ url = "None",
+ name = "None")
+
+
+class Args(object):
+ """Arguments class.
+ Hold all arguments passed to the script and also persistent user data and
+ reference to the addon. It is intended to hold all data necessary for the
+ script.
+ """
+ def __init__(self, *args, **kwargs):
+ """Initialize arguments object.
+ Hold also references to the addon which can't be kept at module level.
+ """
+ self._addon = sys.modules["__main__"]._addon
+ self._addonname = sys.modules["__main__"]._plugin
+ self._addonid = sys.modules["__main__"]._plugId
+ self._cj = None
+
+ for key, value in kwargs.iteritems():
+ if value == "None":
+ kwargs[key] = None
+ else:
+ kwargs[key] = urllib.unquote_plus(kwargs[key])
+ self.__dict__.update(kwargs)
diff --git a/plugin.video.wakanim/resources/lib/login.py b/plugin.video.wakanim/resources/lib/login.py
new file mode 100644
index 0000000..b5920ea
--- /dev/null
+++ b/plugin.video.wakanim/resources/lib/login.py
@@ -0,0 +1,94 @@
+# -*- 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 <http://www.gnu.org/licenses/>.
+
+import os
+import cookielib
+import urllib
+import urllib2
+
+import xbmc
+
+
+def login(username, password, args):
+ """Login and session handler
+ """
+ login_url = "https://www.wakanim.tv/" + args._country + "/v2/account/login?ReturnUrl=%2Fde%2Fv2%2Fdiscover"
+
+ # create cookie path
+ cookiepath = os.path.join(
+ xbmc.translatePath(args._addon.getAddonInfo("profile")).decode("utf-8"),
+ "cookies.lwp")
+
+ # create cookiejar
+ cj = cookielib.LWPCookieJar()
+ args._cj = cj
+
+ # lets urllib2 handle cookies
+ opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cj))
+ opener.addheaders = [("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36")]
+ urllib2.install_opener(opener)
+
+ # check if session exists
+ try:
+ cj.load(cookiepath, ignore_discard=True)
+
+ # check if session is valid
+ response = urllib2.urlopen("https://www.wakanim.tv/" + args._country + "/v2/catalogue")
+ html = response.read()
+
+ if ("Meine Benachrichtigungen verwalten" in html) or ("Gérer mes notifications" in html) or ("Manage my notifications" in html):
+ # session is valid
+ return True
+
+ except IOError:
+ # cookie file does not exist
+ pass
+
+ # build POST data
+ post_data = urllib.urlencode({"username": username,
+ "password": password,
+ "remember": "1"})
+
+ # POST to login page
+ response = urllib2.urlopen(login_url, post_data)
+
+ # check for login string
+ html = response.read()
+
+ if ("Meine Benachrichtigungen verwalten" in html) or ("Gérer mes notifications" in html) or ("Manage my notifications" in html):
+ # save session to disk
+ cj.save(cookiepath, ignore_discard=True)
+ return True
+ else:
+ return False
+
+
+def getCookie(args):
+ """Returns all cookies as string and urlencoded
+ """
+ # create cookie path
+ cookiepath = os.path.join(
+ xbmc.translatePath(args._addon.getAddonInfo("profile")).decode("utf-8"),
+ "cookies.lwp")
+ # save session to disk
+ args._cj.save(cookiepath, ignore_discard=True)
+
+ ret = ""
+ for cookie in args._cj:
+ ret += urllib.urlencode({cookie.name : cookie.value}) + ";"
+
+ return "|User-Agent=Mozilla%2F5.0%20%28Windows%20NT%2010.0%3B%20Win64%3B%20x64%29%20AppleWebKit%2F537.36%20%28KHTML%2C%20like%20Gecko%29%20Chrome%2F60.0.3112.113%20Safari%2F537.36&Cookie=" + ret[:-1]
diff --git a/plugin.video.wakanim/resources/lib/netapi.py b/plugin.video.wakanim/resources/lib/netapi.py
new file mode 100644
index 0000000..32804c5
--- /dev/null
+++ b/plugin.video.wakanim/resources/lib/netapi.py
@@ -0,0 +1,300 @@
+# -*- 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 <http://www.gnu.org/licenses/>.
+
+import re
+import urllib
+import urllib2
+from bs4 import BeautifulSoup
+
+import xbmc
+import xbmcgui
+
+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.encode("utf-8"),
+ "mode": "list_season",
+ "thumb": thumb,
+ "fanart_image": thumb,
+ "episode": li.find("p", {"class": "tooltip_text"}).strong.string.split(" ")[0],
+ "season": li.find("span", {"class": "tooltip_season"}).string.split(" ")[0],
+ "rating": str(10 - len(star) * 2),
+ "plot": plot.contents[3].string.strip().encode("utf-8"),
+ "year": li.time.string},
+ 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.encode("utf-8"),
+ "mode": "list_season",
+ "thumb": thumb,
+ "fanart_image": thumb,
+ "episode": li.find("p", {"class": "tooltip_text"}).strong.string.split(" ")[0],
+ "season": li.find("span", {"class": "tooltip_season"}).string.split(" ")[0],
+ "rating": str(10 - len(star)*2),
+ "plot": plot.contents[3].string.strip().encode("utf-8"),
+ "year": li.time.string},
+ 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_image": 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_image": 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")
+
+ 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",
+ "season": title.encode("utf-8"),
+ "thumb": args.icon,
+ "fanart_image": args.fanart,
+ "episode": args.episode,
+ "rating": args.rating,
+ "plot": args.plot,
+ "year": args.year},
+ 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.season):
+ 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": thumb,
+ "fanart_image": args.fanart,
+ "episode": args.episode,
+ "rating": args.rating,
+ "plot": args.plot,
+ "year": args.year},
+ 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
+
+ # prefer using download able videos
+ if "episode_download_buttons" in html and 1==0: # TODO
+ """
+ div = soup.find("div", {"class": "episode_download_buttons"})
+ if div:
+ for file in reversed(div.find_all("a")):
+ try:
+ url = "https://www.wakanim.tv" + file["href"] + login.getCookie(args)
+ item = xbmcgui.ListItem(args.name, path=url)
+ item.setInfo(type="Video", infoLabels={"Title": args.name,
+ "TVShowTitle": args.name,
+ "episode": args.episode,
+ "rating": args.rating,
+ "plot": args.plot,
+ "year": args.year,
+ "studio": args.studio})
+ item.setThumbnailImage(args.icon)
+ xbmc.Player().play(url, item)
+ return
+ except:
+ pass
+ else:
+ xbmc.log("[PLUGIN] %s: Failed to play video" % args._addonname, xbmc.LOGERROR)
+ xbmcgui.Dialog().ok(args._addonname, args._addon.getLocalizedString(30044))
+ """
+
+ # using stream with hls
+ elif ("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 ("<span>Kostenlos</span>" in html) or ("<span>Gratuit</span>" in html) or ("<span>Free</span>" 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:
+ # file url
+ url = "https://www.wakanim.tv" + matches
+
+ # play stream
+ item = xbmcgui.ListItem(args.name, path=url + login.getCookie(args))
+ item.setInfo(type="Video", infoLabels={"Title": args.name,
+ "TVShowTitle": args.name,
+ "episode": args.episode,
+ "rating": args.rating,
+ "plot": args.plot,
+ "year": args.year})
+ item.setThumbnailImage(args.icon)
+ xbmc.Player().play(url + login.getCookie(args), 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))
diff --git a/plugin.video.wakanim/resources/lib/view.py b/plugin.video.wakanim/resources/lib/view.py
new file mode 100644
index 0000000..a3ef988
--- /dev/null
+++ b/plugin.video.wakanim/resources/lib/view.py
@@ -0,0 +1,137 @@
+# -*- 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 <http://www.gnu.org/licenses/>.
+
+import re
+import sys
+import urllib
+
+import xbmc
+import xbmcgui
+import xbmcplugin
+
+
+def endofdirectory():
+ # Sort methods are required in library mode
+ xbmcplugin.addSortMethod(int(sys.argv[1]), xbmcplugin.SORT_METHOD_NONE)
+
+ # Let xbmc know the script is done adding items to the list
+ dontAddToHierarchy = False
+ xbmcplugin.endOfDirectory(handle = int(sys.argv[1]), updateListing = dontAddToHierarchy)
+
+
+def add_item(args, info, isFolder=True, total_items=0, queued=False, rex=re.compile(r"(?<=mode=)[^&]*"), mediatype="video"):
+ """Add item to directory listing.
+ """
+ # Defaults in dict. Use "None" instead of None so it is compatible for
+ info = set_info_defaults(args, info)
+ u = build_url(info)
+
+ # Create list item
+ li = xbmcgui.ListItem(label = info["title"],
+ iconImage = info["thumb"],
+ thumbnailImage = info["thumb"])
+ if isFolder:
+ li.setInfo(type = mediatype,
+ infoLabels = {"title": info["title"],
+ "plot": info["plot"],
+ "year": info["year"],
+ "episode": info["episode"],
+ "season": info["season"],
+ "rating": info["rating"],
+ "genre": "Anime"})
+ else:
+ li.setInfo(type = mediatype,
+ infoLabels = {"mediatype": "video",
+ "title": info["title"],
+ "plot": info["plot"],
+ "year": info["year"],
+ "episode": info["episode"],
+ "season": info["season"],
+ "rating": info["rating"],
+ "genre": "Anime"})
+
+ li.setArt({"thumb": info["thumb"],
+ "poster": info["thumb"],
+ "banner": info["thumb"],
+ "fanart": info["fanart_image"],
+ "icon": info["thumb"]})
+
+ # Add item to list
+ xbmcplugin.addDirectoryItem(handle = int(sys.argv[1]),
+ url = u,
+ listitem = li,
+ isFolder = isFolder,
+ totalItems = total_items)
+
+
+def build_url(info):
+ # Create params for xbmcplugin module
+ s = sys.argv[0] +\
+ "?url=" + urllib.quote_plus(info["url"]) +\
+ "&mode=" + urllib.quote_plus(info["mode"]) +\
+ "&name=" + urllib.quote_plus(info["title"]) +\
+ "&id=" + urllib.quote_plus(info["id"]) +\
+ "&count=" + urllib.quote_plus(info["count"]) +\
+ "&series_id=" + urllib.quote_plus(info["series_id"]) +\
+ "&filterx=" + urllib.quote_plus(info["filterx"]) +\
+ "&offset=" + urllib.quote_plus(info["offset"]) +\
+ "&icon=" + urllib.quote_plus(info["thumb"]) +\
+ "&complete=" + urllib.quote_plus(info["complete"]) +\
+ "&fanart=" + urllib.quote_plus(info["fanart_image"]) +\
+ "&season=" + urllib.quote_plus(info["season"]) +\
+ "&media_type=" + urllib.quote_plus(info["media_type"]) +\
+ "&year=" + urllib.quote_plus(info["year"]) +\
+ "&playhead=" + urllib.quote_plus(info["playhead"]) +\
+ "&duration=" + urllib.quote_plus(info["duration"]) +\
+ "&episode=" + urllib.quote_plus(info["episode"]) +\
+ "&rating=" + urllib.quote_plus(info["rating"]) +\
+ "&plot=" + urllib.quote_plus(info["plot"])
+ return s
+
+
+def set_info_defaults(args, info):
+ # Defaults in dict. Use "None" instead of None so it is compatible for
+ # quote_plus in parseArgs.
+ info.setdefault("url", "None")
+ info.setdefault("thumb", "DefaultFolder.png")
+ info.setdefault("fanart_image",
+ xbmc.translatePath(args._addon.getAddonInfo("fanart")))
+ info.setdefault("count", "0")
+ info.setdefault("filterx", "None")
+ info.setdefault("id", "None")
+ info.setdefault("series_id", "None")
+ info.setdefault("offset", "0")
+ info.setdefault("season", "1")
+ info.setdefault("series_id", "0")
+ info.setdefault("page_url", "None")
+ info.setdefault("complete", "True")
+ info.setdefault("media_type", "None")
+ info.setdefault("title", "None")
+ info.setdefault("year", "0")
+ info.setdefault("playhead", "0")
+ info.setdefault("duration", "0")
+ info.setdefault("episode", "0")
+ info.setdefault("plot", "None")
+ info.setdefault("percent", "0")
+ info.setdefault("ordering", "0")
+ info.setdefault("rating", "0")
+ info.setdefault("studio", "None")
+ # And set all None to "None"
+ for key, value in info.items():
+ if value == None:
+ info[key] = "None"
+ return info
diff --git a/plugin.video.wakanim/resources/lib/wakanim.py b/plugin.video.wakanim/resources/lib/wakanim.py
new file mode 100644
index 0000000..5ff9a05
--- /dev/null
+++ b/plugin.video.wakanim/resources/lib/wakanim.py
@@ -0,0 +1,124 @@
+# -*- 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 <http://www.gnu.org/licenses/>.
+
+import sys
+
+import xbmc
+import xbmcgui
+import xbmcplugin
+
+import cmdargs
+import login
+import netapi
+import view
+
+
+def main():
+ """Main function for the addon
+ """
+ args = cmdargs.parse_args()
+
+ # check if account is set
+ username = args._addon.getSetting("wakanim_username")
+ password = args._addon.getSetting("wakanim_password")
+
+ # set country
+ args._country = args._addon.getSetting("country")
+ if args._country == "0":
+ args._country = "de"
+ elif args._country == "1":
+ args._country = "fr"
+ elif args._country == "2":
+ args._country = "sc"
+ else:
+ args._country = "de"
+
+ if not (username and password):
+ # open addon settings
+ args._addon.openSettings()
+ return False
+ else:
+ # login
+ success = login.login(username, password, args)
+ if success:
+ # list menue
+ xbmcplugin.setContent(int(sys.argv[1]), "tvshows")
+ check_mode(args)
+ else:
+ # login failed
+ xbmc.log("[PLUGIN] %s: Login failed" % args._addonname, xbmc.LOGERROR)
+ xbmcgui.Dialog().ok(args._addonname, args._addon.getLocalizedString(30040))
+ return False
+
+
+def check_mode(args):
+ """Run mode-specific functions
+ """
+ if hasattr(args, "mode"):
+ mode = args.mode
+ else:
+ # call from other plugin
+ mode = "videoplay"
+ args.name = "Video"
+ args.episode, args.rating, args.plot, args.year, args.icon = ("None",) * 5
+
+ if hasattr(args, "id"):
+ args.url = "/" + args._country + "/v2/catalogue/episode/" + args.id
+ elif hasattr(args, "url"):
+ args.url = args.url[22:]
+ else:
+ mode = None
+
+ if mode is None:
+ showMainMenue(args)
+ elif mode == "catalog":
+ netapi.showCatalog(args)
+ elif mode == "search":
+ netapi.searchAnime(args)
+ elif mode == "downloads":
+ netapi.myDownloads(args)
+ elif mode == "collection":
+ netapi.myCollection(args)
+ elif mode == "list_season":
+ netapi.listSeason(args)
+ elif mode == "list_episodes":
+ netapi.listEpisodes(args)
+ elif mode == "videoplay":
+ netapi.startplayback(args)
+ else:
+ # unkown mode
+ xbmc.log("[PLUGIN] %s: Failed in check_mode '%s'" % (args._addonname, str(mode)), xbmc.LOGERROR)
+ xbmcgui.Dialog().notification(args._addonname, args._addon.getLocalizedString(30041), xbmcgui.NOTIFICATION_ERROR)
+ showMainMenue(args)
+
+
+def showMainMenue(args):
+ """Show main menu
+ """
+ view.add_item(args,
+ {"title": args._addon.getLocalizedString(30020),
+ "mode": "catalog"})
+ view.add_item(args,
+ {"title": args._addon.getLocalizedString(30021),
+ "mode": "search"})
+ view.add_item(args,
+ {"title": args._addon.getLocalizedString(30022),
+ "mode": "downloads"})
+ view.add_item(args,
+ {"title": args._addon.getLocalizedString(30023),
+ "mode": "collection"})
+ view.endofdirectory()
diff --git a/plugin.video.wakanim/resources/settings.xml b/plugin.video.wakanim/resources/settings.xml
new file mode 100644
index 0000000..9cdfd96
--- /dev/null
+++ b/plugin.video.wakanim/resources/settings.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<settings>
+ <setting id="country" type="select" lvalues="30011|30012|30013" label="30010" default="0" />
+ <setting type="sep" />
+ <setting id="wakanim_username" type="text" label="30001" default=""/>
+ <setting id="wakanim_password" type="text" label="30002" option="hidden" default=""/>
+ <setting type="sep" />
+ <setting id="video_quality" type="select" lvalues="30005|30004" label="30003" default="0"/>
+</settings>