summaryrefslogtreecommitdiff
path: root/plugin.video.akibapass/resources/lib
diff options
context:
space:
mode:
Diffstat (limited to 'plugin.video.akibapass/resources/lib')
-rw-r--r--plugin.video.akibapass/resources/lib/__init__.py1
-rw-r--r--plugin.video.akibapass/resources/lib/akibapass.py114
-rw-r--r--plugin.video.akibapass/resources/lib/cmdargs.py51
-rw-r--r--plugin.video.akibapass/resources/lib/login.py95
-rw-r--r--plugin.video.akibapass/resources/lib/netapi.py294
-rw-r--r--plugin.video.akibapass/resources/lib/view.py110
6 files changed, 665 insertions, 0 deletions
diff --git a/plugin.video.akibapass/resources/lib/__init__.py b/plugin.video.akibapass/resources/lib/__init__.py
new file mode 100644
index 0000000..b93054b
--- /dev/null
+++ b/plugin.video.akibapass/resources/lib/__init__.py
@@ -0,0 +1 @@
+# Dummy file to make this directory a package.
diff --git a/plugin.video.akibapass/resources/lib/akibapass.py b/plugin.video.akibapass/resources/lib/akibapass.py
new file mode 100644
index 0000000..5a6e7ac
--- /dev/null
+++ b/plugin.video.akibapass/resources/lib/akibapass.py
@@ -0,0 +1,114 @@
+# -*- coding: utf-8 -*-
+# Akibapass - Watch videos from the german anime platform Akibapass.de on Kodi.
+# Copyright (C) 2016 - 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()
+
+ # check if account is set
+ username = args._addon.getSetting("akiba_username")
+ password = args._addon.getSetting("akiba_password")
+
+ 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
+ elif hasattr(args, "id"):
+ # call from other plugin
+ mode = "videoplay"
+ args.url = "/de/v2/catalogue/episode/" + args.id
+ elif hasattr(args, "url"):
+ # call from other plugin
+ mode = "videoplay"
+ args.url = args.url[24:]
+ else:
+ mode = None
+
+ if not mode:
+ 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)
+ elif mode == "trailer":
+ item = xbmcgui.ListItem(getattr(args, "title", "Title not provided"), path=args.url)
+ xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, item)
+ 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.akibapass/resources/lib/cmdargs.py b/plugin.video.akibapass/resources/lib/cmdargs.py
new file mode 100644
index 0000000..61cc975
--- /dev/null
+++ b/plugin.video.akibapass/resources/lib/cmdargs.py
@@ -0,0 +1,51 @@
+# -*- coding: utf-8 -*-
+# Akibapass - Watch videos from the german anime platform Akibapass.de on Kodi.
+# Copyright (C) 2016 - 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
+import urlparse
+
+
+def parse():
+ """Decode arguments
+ """
+ if (sys.argv[2]):
+ return Args(urlparse.parse_qs(sys.argv[2][1:]))
+ else:
+ return Args({})
+
+
+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, 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:
+ kwargs[key] = urllib.unquote_plus(value[0])
+
+ self.__dict__.update(kwargs)
diff --git a/plugin.video.akibapass/resources/lib/login.py b/plugin.video.akibapass/resources/lib/login.py
new file mode 100644
index 0000000..d8df6ba
--- /dev/null
+++ b/plugin.video.akibapass/resources/lib/login.py
@@ -0,0 +1,95 @@
+# -*- coding: utf-8 -*-
+# Akibapass - Watch videos from the german anime platform Akibapass.de on Kodi.
+# Copyright (C) 2016 - 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.akibapass.de/de/v2/account/login?ReturnUrl=%2Fde%2Fv2"
+
+ # 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")]
+ opener.addheaders = [("Accept-Charset", "utf-8")]
+ 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.akibapass.de/de/v2/catalogue")
+ html = response.read()
+
+ if "Meine pers&#246;nlichen Informationen bearbeiten" 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 pers&#246;nlichen Informationen bearbeiten" 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.akibapass/resources/lib/netapi.py b/plugin.video.akibapass/resources/lib/netapi.py
new file mode 100644
index 0000000..16abaa6
--- /dev/null
+++ b/plugin.video.akibapass/resources/lib/netapi.py
@@ -0,0 +1,294 @@
+# -*- coding: utf-8 -*-
+# Akibapass - Watch videos from the german anime platform Akibapass.de on Kodi.
+# Copyright (C) 2016 - 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 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.akibapass.de/de/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.akibapass.de/de/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.akibapass.de/de/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.akibapass.de/de/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.akibapass.de" + 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")
+ studio = soup.find_all("span", {"class": "border-list_text"})[2].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")
+ try:
+ trailer = soup.find("span", {"class": "js-video-open"})["data-video"]
+ trailer = "plugin://plugin.video.youtube/play/?video_id=" + trailer
+ 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 TypeError:
+ 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", ""),
+ "studio": studio,
+ "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.akibapass.de" + 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.akibapass.de" + args.url)
+ html = response.read()
+
+ soup = BeautifulSoup(html, "html.parser")
+
+ # check if not premium
+ if "Dieses Video ist nur f&#252;r Nutzer eines Abos verf&#252;gbar" 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.akibapass.de" + a)
+ html = response.read()
+
+ # reload page
+ response = urllib2.urlopen("https://www.akibapass.de" + 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 "Klicke hier, um den Flash-Player zu benutzen" in html:
+ # get stream file
+ regex = r"file: \"(.*?)\","
+ matches = re.search(regex, html).group(1)
+
+ if matches:
+ # manifest url
+ url = "https://www.akibapass.de" + 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))
diff --git a/plugin.video.akibapass/resources/lib/view.py b/plugin.video.akibapass/resources/lib/view.py
new file mode 100644
index 0000000..f72b985
--- /dev/null
+++ b/plugin.video.akibapass/resources/lib/view.py
@@ -0,0 +1,110 @@
+# -*- coding: utf-8 -*-
+# Akibapass - Watch videos from the german anime platform Akibapass.de on Kodi.
+# Copyright (C) 2016 - 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
+
+import xbmc
+import xbmcgui
+import xbmcplugin
+
+
+# keys allowed in setInfo
+types = ["count", "size", "date", "genre", "year", "episode", "season", "top250", "tracknumber",
+ "rating", "userrating", "watched", "playcount", "overlay", "cast", "castandrole", "director",
+ "mpaa", "plot", "plotoutline", "title", "originaltitle", "sorttitle", "duration", "studio",
+ "tagline", "writer", "tvshowtitle", "premiered", "status", "code", "aired", "credits", "lastplayed",
+ "album", "artist", "votes", "trailer", "dateadded", "mediatype"]
+
+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
+ xbmcplugin.endOfDirectory(handle = int(sys.argv[1]))
+
+
+def add_item(args, info, isFolder=True, total_items=0, mediatype="video"):
+ """Add item to directory listing.
+ """
+
+ # create list item
+ li = xbmcgui.ListItem(label = info["title"])
+
+ # get infoLabels
+ infoLabels = make_infolabel(args, info)
+ infoLabels["genre"] = "Anime"
+
+ # get url
+ u = build_url(args, info)
+
+ if isFolder:
+ # directory
+ li.setInfo(mediatype, infoLabels)
+ else:
+ # playable video
+ infoLabels["mediatype"] = "video"
+ li.setInfo(mediatype, infoLabels)
+ li.setProperty("IsPlayable", "true")
+
+ # set media image
+ li.setArt({"thumb": info.get("thumb", "DefaultFolder.png"),
+ "poster": info.get("thumb", "DefaultFolder.png"),
+ "banner": info.get("thumb", "DefaultFolder.png"),
+ "fanart": info.get("fanart", xbmc.translatePath(args._addon.getAddonInfo("fanart"))),
+ "icon": info.get("thumb", "DefaultFolder.png")})
+
+ # add item to list
+ xbmcplugin.addDirectoryItem(handle = int(sys.argv[1]),
+ url = u,
+ listitem = li,
+ isFolder = isFolder,
+ totalItems = total_items)
+
+
+def build_url(args, info):
+ """Create url
+ """
+ s = ""
+ # step 1 copy new information from info
+ for key, value in info.iteritems():
+ if value:
+ s = s + "&" + key + "=" + urllib.quote_plus(value)
+
+ # step 2 copy old information from args, but don't append twice
+ for key, value in args.__dict__.iteritems():
+ if value and key in types and not "&" + str(key) + "=" in s:
+ s = s + "&" + key + "=" + urllib.quote_plus(value)
+
+ return sys.argv[0] + "?" + s[1:]
+
+
+def make_infolabel(args, info):
+ """Generate infoLabels from existing dict
+ """
+ infoLabels = {}
+ # step 1 copy new information from info
+ for key, value in info.iteritems():
+ if value and key in types:
+ infoLabels[key] = value
+
+ # step 2 copy old information from args, but don't overwrite
+ for key, value in args.__dict__.iteritems():
+ if value and key in types and key not in infoLabels:
+ infoLabels[key] = value
+
+ return infoLabels