diff --git a/addon.xml b/addon.xml
index 19d71123..d8a62cbb 100644
--- a/addon.xml
+++ b/addon.xml
@@ -28,6 +28,7 @@
+
@@ -44,6 +45,31 @@
Möglicherweise sind einge Teile dieses Addons in Ihrem Land illegal, Sie sollten dies unbedingt vor der Installation überprüfen. Diese Plugin verwendet pyDes von Todd Whiteman
+
+
+
+
+
+
+
+
+
+ video
+
+
+ all
+ Amazon Prime Video Streaming
+ Amazon Prime Instant Video
+ Movies and Television Shows for Prime Members
+ Filme und Serien für Amazon Prime Mitglieder
+ Some parts of this addon may not be legal in your country of residence - please check with your local laws before installing.
+ Möglicherweise sind einge Teile dieses Addons in Ihrem Land illegal, Sie sollten dies unbedingt vor der Installation überprüfen.
+
+
https://github.com/jjlee/mechanize
+
+
+
+
+
+
+ A pure python module which implements the DES and Triple-DES encryption algorithms.
+ http://twhiteman.netfirms.com/des.html
+ Public Domain
+ all
+
+
+
diff --git a/addon.xml.md5 b/addon.xml.md5
index 7cd9d205..b3f809a7 100644
--- a/addon.xml.md5
+++ b/addon.xml.md5
@@ -1 +1 @@
-92a6ca245d4356e0f8ffc643514d7c55
+13386e46d4a8a147c9933f8fbdd9f5af
diff --git a/plugin.video.amazon-test/addon.xml b/plugin.video.amazon-test/addon.xml
new file mode 100644
index 00000000..06ca4985
--- /dev/null
+++ b/plugin.video.amazon-test/addon.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+ video
+
+
+ all
+ Amazon Prime Video Streaming
+ Amazon Prime Instant Video
+ Movies and Television Shows for Prime Members
+ Filme und Serien für Amazon Prime Mitglieder
+ Some parts of this addon may not be legal in your country of residence - please check with your local laws before installing.
+ Möglicherweise sind einge Teile dieses Addons in Ihrem Land illegal, Sie sollten dies unbedingt vor der Installation überprüfen.
+
+
diff --git a/plugin.video.amazon-test/default.py b/plugin.video.amazon-test/default.py
new file mode 100644
index 00000000..a1826ffe
--- /dev/null
+++ b/plugin.video.amazon-test/default.py
@@ -0,0 +1,1021 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+#from __future__ import unicode_literals
+from BeautifulSoup import BeautifulSoup, BeautifulStoneSoup, Tag, NavigableString
+from datetime import date
+from pyDes import *
+import uuid
+import cookielib
+import mechanize
+import sys
+import urllib
+import urllib2
+import re
+import os
+import xbmcplugin
+import xbmcgui
+import xbmcaddon
+import xbmc
+import urlparse
+import base64
+import binascii
+import hmac
+import time
+import random
+import subprocess
+import hashlib
+import hmac
+
+try: from demjson import demjson
+except: import demjson
+try: from sqlite3 import dbapi2 as sqlite
+except: from pysqlite2 import dbapi2 as sqlite
+
+addon = xbmcaddon.Addon()
+pluginhandle = int(sys.argv[1])
+__plugin__ = addon.getAddonInfo('name')
+__authors__ = addon.getAddonInfo('author')
+__credits__ = ""
+__version__ = addon.getAddonInfo('version')
+ProfilPath = xbmc.translatePath('special://masterprofile/').decode('utf-8')
+PluginPath = addon.getAddonInfo('path').decode('utf-8')
+DataPath = xbmc.translatePath('special://profile/addon_data/' + addon.getAddonInfo('id')).decode('utf-8')
+HomePath = xbmc.translatePath('special://home').decode('utf-8')
+userinput = os.path.join(PluginPath, 'tools', 'userinput.exe' )
+waitsec = int(addon.getSetting("clickwait")) * 1000
+waitprepin = int(addon.getSetting("waitprepin")) * 1000
+pin = addon.getSetting("pin")
+waitpin = int(addon.getSetting("waitpin")) * 1000
+tvdb_art = addon.getSetting("tvdb_art")
+tmdb_art = addon.getSetting("tmdb_art")
+showfanart = addon.getSetting("useshowfanart")
+dispShowOnly = addon.getSetting("disptvshow")
+MaxResults = int(addon.getSetting("items_perpage"))
+osLinux = xbmc.getCondVisibility('system.platform.linux')
+osOsx = xbmc.getCondVisibility('system.platform.osx')
+osWin = xbmc.getCondVisibility('system.platform.windows')
+screenWidth = int(xbmc.getInfoLabel('System.ScreenWidth'))
+screenHeight = int(xbmc.getInfoLabel('System.ScreenHeight'))
+playPlugin = ['plugin.program.browser.launcher', 'plugin.program.chrome.launcher']
+selPlugin = playPlugin[int(addon.getSetting("playmethod"))]
+tmdb = base64.b64decode('YjM0NDkwYzA1NmYwZGQ5ZTNlYzlhZjIxNjdhNzMxZjQ=')
+tvdb = base64.b64decode('MUQ2MkYyRjkwMDMwQzQ0NA==')
+CookieFile = os.path.join(DataPath, 'cookies.lwp')
+DefaultFanart = os.path.join(PluginPath, 'fanart.jpg')
+country = int(addon.getSetting("country"))
+BaseUrl = 'https://www.amazon.' + ['de', 'co.uk', 'com', 'co.jp'][country]
+ATVUrl = 'https://atv-ps%s.amazon.com' % ['-eu', '-eu', '', '-fe'][country]
+MarketID = ['A1PA6795UKMFR9', 'A1F83G8C2ARO7P', 'ATVPDKIKX0DER', 'A1VC38T7YXB528'][country]
+Language = ['de', 'en', 'en', 'jp'][country]
+menuFile = os.path.join(DataPath, 'menu-%s.json' % MarketID)
+na = 'not available'
+LogFile = True
+UserAgent = 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2532.0 Safari/537.36'
+watchlist = 'wl'
+library = 'yvl'
+
+#ids: A28RQHJKHM2A2W - ps3 / AFOQV1TK6EU6O - ps4 / A1IJNVP3L4AY8B - samsung / A2E0SNTXJVT7WK - bueller /
+# ADVBD696BHNV5 - montoya / A3VN4E5F7BBC7S - roku / A1MPSLFC7L5AFK - kindle
+TypeIDs = {'GetCategoryList': 'firmware=fmw:15-app:1.1.23&deviceTypeID=A1MPSLFC7L5AFK',
+ 'All': 'firmware=fmw:045.01E01164A-app:4.7&deviceTypeID=A3VN4E5F7BBC7S'}
+langID = {'movie':30165, 'series':30166, 'season':30167, 'episode':30173}
+OfferGroup = 'OfferGroups=B0043YVHMY'
+Dialog = xbmcgui.Dialog()
+pDialog = xbmcgui.DialogProgress()
+
+if (addon.getSetting('enablelibraryfolder') == 'true'):
+ MOVIE_PATH = os.path.join(xbmc.translatePath(addon.getSetting('customlibraryfolder')),'Movies').decode('utf-8')
+ TV_SHOWS_PATH = os.path.join(xbmc.translatePath(addon.getSetting('customlibraryfolder')),'TV').decode('utf-8')
+else:
+ MOVIE_PATH = os.path.join(DataPath,'Movies')
+ TV_SHOWS_PATH = os.path.join(DataPath,'TV')
+
+def setView(content, view=False, updateListing=False):
+ # 501-POSTER WRAP 503-MLIST3 504=MLIST2 508-FANARTPOSTER
+ if content == 'movie':
+ ctype = 'movies'
+ cview = 'movieview'
+ elif content == 'series':
+ ctype = 'tvshows'
+ cview = 'showview'
+ elif content == 'season':
+ ctype = 'tvshows'
+ cview = 'seasonview'
+ elif content == 'episode':
+ ctype = 'episodes'
+ cview = 'episodeview'
+
+ confluence_views = [500,501,502,503,504,508,-1]
+ xbmcplugin.setContent(pluginhandle, ctype)
+ viewenable = addon.getSetting("viewenable")
+ if viewenable == 'true' and view:
+ viewid = confluence_views[int(addon.getSetting(cview))]
+ if viewid == -1:
+ viewid = int(addon.getSetting(cview.replace('view', 'id')))
+ xbmc.executebuiltin('Container.SetViewMode(%s)' % viewid)
+ xbmcplugin.endOfDirectory(pluginhandle,updateListing=updateListing)
+
+def getURL( url, host=BaseUrl.split('//')[1], useCookie=False, silent=False, headers=None):
+ cj = cookielib.LWPCookieJar()
+ if useCookie and os.path.isfile(CookieFile):
+ cj.load(CookieFile, ignore_discard=True, ignore_expires=True)
+ Log('getURL: '+url)
+ if not headers: headers = [('User-Agent', UserAgent ), ('Host', host)]
+ try:
+ opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cj),urllib2.HTTPRedirectHandler)
+ opener.addheaders = headers
+ usock = opener.open(url)
+ response = usock.read()
+ usock.close()
+ except urllib2.URLError, e:
+ Log('Error reason: %s' % e, xbmc.LOGERROR)
+ return False
+ return response
+
+def getATVData(mode, query='', version=2, useCookie=True):
+ if '?' in query: query = query.split('?')[1]
+ if query:
+ query = '&IncludeAll=T&AID=T&' + query
+ if TypeIDs.has_key(mode): deviceTypeID = TypeIDs[mode]
+ else: deviceTypeID = TypeIDs['All']
+ if not '/' in mode: mode = 'catalog/' + mode
+ parameter = '%s&deviceID=%s&format=json&version=%s&formatVersion=3&marketplaceId=%s' % (deviceTypeID, deviceID, version, MarketID)
+ data = getURL('%s/cdp/%s?%s%s' % (ATVUrl, mode, parameter, query), useCookie=useCookie)
+ if not data: return None
+ jsondata = demjson.decode(data)
+ if jsondata['message']['statusCode'] != "SUCCESS":
+ Log('Error Code: ' + jsondata['message']['body']['code'], xbmc.LOGERROR)
+ return None
+ return jsondata['message']['body']
+
+def addDir(name, mode, url='', infoLabels=None, opt='', catalog='Browse', cm=False, page=1, export=False):
+ if type(url) == type(unicode()): url = url.encode('utf-8')
+ u = u'%s?mode=%s&url=%s&page=%s&opt=%s&cat=%s' % (sys.argv[0], mode, urllib.quote_plus(url), page, opt, catalog)
+ if infoLabels:
+ thumb = infoLabels['Thumb']
+ fanart = infoLabels['Fanart']
+ else: fanart = thumb = DefaultFanart
+ if export:
+ Export(infoLabels, u)
+ return
+ item=xbmcgui.ListItem(name, iconImage="DefaultFolder.png", thumbnailImage=thumb)
+ item.setProperty('fanart_image',fanart)
+ item.setProperty('IsPlayable', 'false')
+ if infoLabels and infoLabels.has_key('TotalSeasons'):
+ item.setProperty('TotalSeasons', str(infoLabels['TotalSeasons']))
+ if infoLabels: item.setInfo(type='Video', infoLabels=infoLabels)
+ if cm: item.addContextMenuItems(cm, replaceItems=False)
+ xbmcplugin.addDirectoryItem(pluginhandle, u, item, isFolder=True)
+
+def addVideo(name, asin, infoLabels, cm=[], export=False):
+ u = '%s?asin=%s&mode=PlayVideo&name=%s&adult=%s' % (sys.argv[0], asin, urllib.quote_plus(name.encode('utf-8')), infoLabels['isAdult'])
+
+ item = xbmcgui.ListItem(name, thumbnailImage=infoLabels['Thumb'])
+ item.setProperty('fanart_image', infoLabels['Fanart'])
+ if infoLabels.has_key('Poster'): item.setArt({'tvshow.poster': infoLabels['Poster']})
+ else: item.setArt({'poster': infoLabels['Thumb']})
+ item.setProperty('IsPlayable', 'false')
+
+ if infoLabels['isHD']:
+ item.addStreamInfo('video', { 'width':1280 ,'height' : 720 })
+ else:
+ item.addStreamInfo('video', { 'width':720 ,'height' : 480 })
+ if infoLabels['AudioChannels']: item.addStreamInfo('audio', { 'codec': 'ac3' ,'channels': int(infoLabels['AudioChannels']) })
+ if infoLabels['TrailerAvailable']:
+ infoLabels['Trailer'] = u + '&trailer=1&selbitrate=0'
+ u += '&trailer=0&selbitrate=0'
+ if export:
+ Export(infoLabels, u)
+ else:
+ cm.insert(0, (getString(30101), 'Action(ToggleWatched)') )
+ item.setInfo(type='Video', infoLabels=infoLabels)
+ item.addContextMenuItems( cm , replaceItems=False )
+ xbmcplugin.addDirectoryItem(pluginhandle, u, item, isFolder=False)
+
+def MainMenu():
+ loadCategories()
+ cm_wl = [(getString(30185) % 'Watchlist', 'XBMC.RunPlugin(%s?mode=getList&url=%s&export=1)' % (sys.argv[0], watchlist) )]
+ cm_lb = [(getString(30185) % getString(30100), 'XBMC.RunPlugin(%s?mode=getList&url=%s&export=1)' % (sys.argv[0], library) )]
+ addDir('Watchlist', 'getList', watchlist, cm=cm_wl)
+ addDir(getString(30104), 'listCategories', "[0]", opt=30143)
+ addDir(getString(30107), 'listCategories', "[1]", opt=30160)
+ addDir(getString(30108), 'Search', '')
+ addDir(getString(30100), 'getList', library, cm=cm_lb)
+ xbmcplugin.endOfDirectory(pluginhandle, updateListing=False)
+
+def Search():
+ keyboard = xbmc.Keyboard('')
+ keyboard.doModal()
+ if (keyboard.isConfirmed()):
+ searchString=keyboard.getText().strip()
+ if searchString:
+ url = '%s&searchString=%s' % (OfferGroup, urllib.quote_plus(searchString))
+ listContent('Search', url, 1, 'search')
+
+def loadCategories(force=False):
+ if os.path.exists(menuFile) and not force:
+ ftime = os.path.getmtime(menuFile)
+ ctime = time.time()
+ if ctime - ftime < 3 * 3600:
+ return demjson.decode_file(menuFile)
+
+ data = getATVData('GetCategoryList')
+ json = []
+ if country < 2:
+ json.append(data['categories'][2]['categories'][0]['categories'])
+ json.append(data['categories'][3]['categories'][0]['categories'])
+ else:
+ json.append(data['categories'][2]['categories'][2]['categories'])
+ json.append(data['categories'][3]['categories'][2]['categories'])
+ demjson.encode_to_file(menuFile, json, overwrite=True)
+ return json
+
+def listCategories(path, root=None):
+ data = loadCategories()
+ exec 'cat = data' + path.__str__()
+ if root:
+ url = OfferGroup + '&OrderBy=Title&ContentType='
+ if root == '30160': url += 'TVSeason&RollupToSeries=T'
+ else: url += 'Movie'
+ addDir(getString(int(root)), 'listContent', url)
+ for pos, item in enumerate(cat):
+ mode = None
+ opt = ''
+ if not item.has_key('title'): continue
+ name = item['title']
+ if item.has_key('categories'):
+ mode = 'listCategories'
+ url = "%s[%s]['categories']" % (path, pos)
+ elif item.has_key('query'):
+ mode = 'listContent'
+ opt = 'listcat'
+ url = item['query'].replace('RollupToSeason', 'RollupToSeries').replace('\n','').replace("\n",'')
+ if mode:
+ addDir(name, mode, url, opt=opt)
+ xbmcplugin.endOfDirectory(pluginhandle)
+
+def listContent(catalog, url, page, parent, export=False):
+ oldurl = url
+ page = int(page)
+ ResPage = MaxResults
+ if export: ResPage = 250
+ url += '&NumberOfResults=%s&StartIndex=%s' % (ResPage+1, (page-1)*ResPage)
+
+ if page != 1 and not export:
+ addDir(' --= %s =--' % (getString(30112) % int(page-1)), 'listContent', oldurl, page=page-1, catalog=catalog, opt=parent)
+ titles = getATVData(catalog, url)
+ if not titles or not len(titles['titles']):
+ if parent == 'search': Dialog.ok(__plugin__, getString(30202))
+ else: Dialog.ok(__plugin__, getString(30127))
+ return
+ titles = titles['titles']
+ for item in titles[0:ResPage]:
+ mode = None
+ if not item.has_key('title'): continue
+ contentType, infoLabels = getInfos(item)
+ name = infoLabels['Title']
+ if infoLabels.has_key('DisplayTitle'): name = infoLabels['DisplayTitle']
+ asin = item['titleId']
+ cm = []
+ wlmode = 0
+ if parent == watchlist: wlmode = 1
+ cm.append((getString(wlmode+30180) % getString(langID[contentType]), 'XBMC.RunPlugin(%s?mode=WatchList&url=%s&opt=%s)' % (sys.argv[0], asin, wlmode )))
+ cm.append((getString(30185) % getString(langID[contentType]), 'XBMC.RunPlugin(%s?mode=getList&url=%s&export=1)' % (sys.argv[0], asin)))
+ cm.append((getString(30186), 'XBMC.RunPlugin(%s?mode=UpdateLibrary)' % sys.argv[0]))
+ name = cleanTitle(name)
+ if contentType == 'movie' or contentType == 'episode':
+ addVideo(name, asin, infoLabels, cm, export)
+ else:
+ mode = 'listContent'
+ url = item['childTitles'][0]['feedUrl']
+ if contentType == 'season':
+ name = formatSeason(infoLabels, parent)
+ if parent != library and parent != '':
+ curl = 'SeriesASIN=%s&ContentType=TVEpisode&RollupToSeason=T&IncludeBlackList=T&%s' % (infoLabels['SeriesAsin'], OfferGroup)
+ cm.insert(0, (getString(30182), 'XBMC.Container.Update(%s?mode=listContent&cat=Browse&url=%s&page=1)' % (sys.argv[0], urllib.quote_plus(curl))))
+
+ if export:
+ url = re.sub(r'contentype=\w+', 'ContentType=TVEpisode', url, flags=re.IGNORECASE)
+ url = re.sub(r'&rollupto\w+=\w+', '', url, flags=re.IGNORECASE)
+ listContent('Browse', url, 1, '', export)
+ else:
+ addDir(name, mode, url, infoLabels, cm=cm, export=export)
+ if len(titles) > ResPage:
+ if export:
+ listContent(catalog, oldurl, page+1, parent, export)
+ else:
+ addDir(' --= %s =--' % (getString(30111) % int(page+1)), 'listContent', oldurl, page=page+1, catalog=catalog, opt=parent)
+ if not export: setView(contentType, True)
+
+def cleanTitle(title):
+ if title.isupper():
+ title = title.title().replace('[Ov]', '[OV]').replace('Bc', 'BC')
+ title = title.replace(u'\u2013', '-').replace(u'\u00A0', ' ').replace('[dt./OV]', '')
+ return title.strip()
+
+def Export(infoLabels, url):
+ content = infoLabels['contentType']
+ ExportPath = TV_SHOWS_PATH
+ language = 'ger'
+
+ if content == 'movie':
+ isEpisode = False
+ ExportPath = MOVIE_PATH
+ nfoType = 'movie'
+ title = infoLabels['Title']
+ else:
+ isEpisode = True
+ title = infoLabels['TVShowTitle']
+
+ tl = title.lower()
+ if '[omu]' in tl or '[ov]' in tl or ' omu' in tl: language = ''
+ filename = re.sub(r'\[.*| omu| ov', '', title, flags=re.IGNORECASE).strip()
+
+ if isEpisode:
+ infoLabels['TVShowTitle'] = filename
+ ExportPath = os.path.join(ExportPath, cleanName(filename))
+ nfoType = 'episodedetails'
+ CreateDirectory(ExportPath)
+ filename = 'S%02dE%02d - %s' % (infoLabels['Season'], infoLabels['Episode'], infoLabels['Title'])
+ else:
+ if infoLabels['Year']: filename = '%s (%s)' % (filename, infoLabels['Year'])
+
+ CreateInfoFile(filename, ExportPath, nfoType, infoLabels, language)
+ SaveFile(filename + '.strm', url, ExportPath)
+ Log('Export: ' + filename)
+
+def WatchList(asin, remove):
+ action = 'add'
+ if remove: action = 'remove'
+ url = BaseUrl + '/gp/video/watchlist/?toggleOnWatchlist=1&action=%s&ASIN=%s' % (action, asin)
+ data = getURL(url, useCookie=True)
+ if asin in data:
+ Log(asin + ' added')
+ else:
+ Log(asin + ' removed')
+ xbmc.executebuiltin('Container.Refresh')
+
+def getArtWork(infoLabels, contentType):
+ if contentType == 'movie' and tmdb_art == '0': return
+ if contentType != 'movie' and tvdb_art == '0': return
+ c = db.cursor()
+ extra = ''
+ season = -2
+ asins = infoLabels['Asins']
+ infoLabels['Banner'] = None
+ if contentType == 'series': season = -1
+ if contentType == 'season' or contentType == 'episode': asins = infoLabels['SeriesAsin']
+ if infoLabels.has_key('Season'): season = int(infoLabels['Season'])
+ if season > -2: extra = ' and season = %s' % season
+ for asin in asins.split(','):
+ result = c.execute('select poster,fanart,banner from art where asin like (?)' + extra, ('%' + asin + '%',)).fetchone()
+ if result:
+ if result[0] and contentType != 'episode' and result[0] != na: infoLabels['Thumb'] = result[0]
+ if result[0] and contentType != 'movie' and result[0] != na: infoLabels['Poster'] = result[0]
+ if result[1] and result[1] != na: infoLabels['Fanart'] = result[1]
+ if result[2] and result[2] != na: infoLabels['Banner'] = result[2]
+ if season > -1:
+ result = c.execute('select poster, fanart from art where asin like (?) and season = -1', ('%' + asin + '%',)).fetchone()
+ if result:
+ if result[0] and result[0] != na and contentType == 'episode' : infoLabels['Poster'] = result[0]
+ if result[1] and result[1] != na and showfanart == 'true': infoLabels['Fanart'] = result[1]
+ return infoLabels
+ elif season > -1 and showfanart == 'true':
+ result = c.execute('select poster,fanart from art where asin like (?) and season = -1', ('%' + asin + '%',)).fetchone()
+ if result:
+ if result[0] and result[0] != na and contentType == 'episode' : infoLabels['Poster'] = result[0]
+ if result[1] and result[1] != na: infoLabels['Fanart'] = result[1]
+
+ c.close()
+ if contentType != 'episode':
+ title = infoLabels['Title']
+ if contentType == 'season': title = infoLabels['TVShowTitle']
+ if type(title) == type(unicode()): title = title.encode('utf-8')
+ xbmc.executebuiltin('RunPlugin(%s?mode=loadArtWork&asins=%s&title=%s&year=%s&ct=%s)' % (sys.argv[0], urllib.quote_plus(asins), urllib.quote_plus(title), infoLabels['Year'], contentType))
+ return infoLabels
+
+def loadArtWork(asins, title, year, contentType):
+ seasons = None
+ season_number = None
+ poster = None
+ fanart = None
+ title = title.lower().replace('?', '').replace('omu', '').split('(')[0].split('[')[0].strip()
+
+ if contentType == 'movie':
+ fanart = getTMDBImages(title, year=year)
+ if contentType == 'season' or contentType == 'series':
+ seasons, poster, fanart = getTVDBImages(title)
+ if not fanart: fanart = getTMDBImages(title, content='tv')
+ season_number = -1
+ content = getATVData('GetASINDetails', 'ASINList='+asins)['titles'][0]
+ asins = getAsins(content, False)
+ del content
+
+ cur = db.cursor()
+ cur.execute('insert or ignore into art values (?,?,?,?,?,?)', (asins, season_number, poster, None, fanart, date.today()))
+ if seasons:
+ for season, url in seasons.items():
+ cur.execute('insert or ignore into art values (?,?,?,?,?,?)', (asins, season, url, None, None, date.today()))
+ db.commit()
+ cur.close()
+
+def getTVDBImages(title, imdb=None, id=None):
+ posterurl = fanarturl = None
+ splitter = [' - ', ': ', ', ']
+ if country == 0 or country == 3:
+ langcodes = [Language, 'en']
+ else: langcodes = ['en']
+ TVDB_URL = 'http://www.thetvdb.com/banners/'
+ while not id:
+ tv = urllib.quote_plus(title)
+ result = getURL('http://www.thetvdb.com/api/GetSeries.php?seriesname=%s&language=%s' % (tv, Language), silent=True)
+ soup = BeautifulSoup(result)
+ id = soup.find('seriesid')
+ if id:
+ id = id.string
+ else:
+ oldtitle = title
+ for splitchar in splitter:
+ if title.count(splitchar):
+ title = title.split(splitchar)[0]
+ break
+ if title == oldtitle:
+ break
+ if not id: return None, None, None
+ soup = BeautifulSoup(getURL('http://www.thetvdb.com/api/%s/series/%s/banners.xml' % (tvdb, id), silent=True))
+ seasons = {}
+ for lang in langcodes:
+ for datalang in soup.findAll('language'):
+ if datalang.string == lang:
+ data = datalang.parent
+ if data.bannertype.string == 'fanart' and not fanarturl: fanarturl = TVDB_URL + data.bannerpath.string
+ if data.bannertype.string == 'poster' and not posterurl: posterurl = TVDB_URL + data.bannerpath.string
+ if data.bannertype.string == data.bannertype2.string == 'season':
+ snr = data.season.string
+ if not seasons.has_key(snr):
+ seasons[snr] = TVDB_URL + data.bannerpath.string
+ return seasons, posterurl, fanarturl
+
+def getTMDBImages(title, imdb=None, content='movie', year=None):
+ fanart = poster = id = None
+ splitter = [' - ', ': ', ', ']
+ TMDB_URL = 'http://image.tmdb.org/t/p/original'
+ yearorg = year
+
+ while not id:
+ str_year = ''
+ if year: str_year = '&year=' + str(year)
+ movie = urllib.quote_plus(title)
+ result = getURL('http://api.themoviedb.org/3/search/%s?api_key=%s&language=%s&query=%s%s' % (content, tmdb, Language, movie, str_year), silent=True)
+ if not result:
+ Log('Fanart: Pause 5 sec...')
+ xbmc.sleep(5000)
+ continue
+ data = demjson.decode(result)
+ if data['total_results'] > 0:
+ result = data['results'][0]
+ if result['backdrop_path']: fanart = TMDB_URL + result['backdrop_path']
+ if result['poster_path']: poster = TMDB_URL + result['poster_path']
+ id = result['id']
+ elif year:
+ year = 0
+ else:
+ year = yearorg
+ oldtitle = title
+ for splitchar in splitter:
+ if title.count(splitchar):
+ title = title.split(splitchar)[0]
+ break
+ if title == oldtitle:
+ break
+ if content == 'movie' and id and not fanart:
+ fanart = na
+ return fanart
+
+def formatSeason(infoLabels, parent):
+ name = ''
+ season = infoLabels['Season']
+ if parent:
+ name = infoLabels['TVShowTitle'] + ' - '
+ if season != 0 and len(str(season)) < 3: name += getString(30167, True) + ' ' + str(season)
+ elif len(str(season)) > 2: name += getString(30168, True) + str(season)
+ else: name += getString(30169, True)
+ return cleanTitle(name)
+
+def getList(list, export):
+ extraArgs = ''
+ if not os.path.isfile(CookieFile):
+ MechanizeLogin()
+ if list == watchlist or list == library:
+ asins_tv = scrapAsins('/gp/aw/%s/?filter=tv&pageSize=1000&sortBy=date' % list)
+ asins_movie = scrapAsins('/gp/aw/%s/?filter=movie&pageSize=1000&sortBy=date' % list)
+ else:
+ asins_movie = list
+ asins_tv = ''
+ url = 'ASINList='
+ if dispShowOnly == 'true': extraArgs = '&RollupToSeries=T'
+ if list == watchlist: extraArgs += '&'+OfferGroup
+ if export:
+ url += asins_movie + ',' + asins_tv
+ SetupLibrary()
+ listContent('GetASINDetails', url, 1, list, export)
+ else:
+ addDir(getString(30104), 'listContent', url+asins_movie, catalog='GetASINDetails', opt=list)
+ addDir(getString(30107), 'listContent', url+asins_tv+extraArgs, catalog='GetASINDetails', opt=list)
+ xbmcplugin.endOfDirectory(pluginhandle, updateListing=False)
+
+def Log(msg, level=xbmc.LOGNOTICE):
+ if type(msg) == type(unicode()):
+ msg = msg.encode('utf-8')
+ #WriteLog(msg)
+ xbmc.log('[%s] %s' % (__plugin__, msg), level)
+
+def WriteLog(data, path=os.path.join(HomePath, 'amazon-test.log')):
+ if not LogFile: return
+ if type(data) == type(unicode()): data = data.encode('utf-8')
+ file = open(path, 'a')
+ data = time.strftime('[%d/%H:%M:%S] ', time.localtime()) + data.__str__()
+ file.write(data)
+ file.write('\n')
+ file.close()
+
+def getString(id, enc=False):
+ if enc: return addon.getLocalizedString(id).encode('utf-8')
+ return addon.getLocalizedString(id)
+
+def getAsins(content, crIL=True):
+ if crIL:
+ infoLabels={'Plot': None, 'MPAA': None, 'Cast': [], 'Year': None, 'Premiered': None, 'Rating': None, 'Votes': None, 'isAdult': 0, 'Director': None,
+ 'Genre': None, 'Studio': None, 'Thumb': None, 'Fanart': None, 'isHD': False, 'isPrime': True, 'AudioChannels': 1, 'TrailerAvailable': False}
+ asins = ''
+ if content.has_key('titleId'):
+ asins += content['titleId']
+ titleId = content['titleId']
+ for format in content['formats']:
+ hasprime = False
+ for offer in format['offers']:
+ if offer['offerType'] == 'SUBSCRIPTION' and crIL:
+ hasprime = True
+ infoLabels['isPrime'] = True
+ elif offer.has_key('asin'):
+ newasin = offer['asin']
+ if format['videoFormatType'] == 'HD' and crIL:
+ if (hasprime):
+ infoLabels['isHD'] = True
+ if newasin not in asins:
+ asins += ',' + newasin
+ if crIL:
+ if 'STEREO' in format['audioFormatTypes']: infoLabels['AudioChannels'] = 2
+ if 'AC_3_5_1' in format['audioFormatTypes']: infoLabels['AudioChannels'] = 6
+ del content
+
+ if crIL:
+ infoLabels['Asins'] = asins
+ return infoLabels
+ return asins
+
+def getInfos(item):
+ infoLabels = getAsins(item)
+ infoLabels['Title'] = item['title']
+ infoLabels['contentType'] = contentType = item['contentType'].lower()
+
+ if item['formats'][0].has_key('images'):
+ try:
+ thumbnailUrl = item['formats'][0]['images'][0]['uri']
+ thumbnailFilename = thumbnailUrl.split('/')[-1]
+ thumbnailBase = thumbnailUrl.replace(thumbnailFilename,'')
+ infoLabels['Thumb'] = thumbnailBase+thumbnailFilename.split('.')[0]+'.jpg'
+ except: pass
+ if item.has_key('synopsis'):
+ infoLabels['Plot'] = item['synopsis']
+ if item.has_key('releaseOrFirstAiringDate'):
+ infoLabels['Premiered'] = item['releaseOrFirstAiringDate']['valueFormatted'].split('T')[0]
+ infoLabels['Year'] = int(infoLabels['Premiered'].split('-')[0])
+ if item.has_key('studioOrNetwork'):
+ infoLabels['Studio'] = item['studioOrNetwork']
+ if item.has_key('regulatoryRating'):
+ if item['regulatoryRating'] == 'not_checked': infoLabels['MPAA'] = getString(30171)
+ else: infoLabels['MPAA'] = getString(30170) + item['regulatoryRating']
+ if item.has_key('starringCast'):
+ infoLabels['Cast'] = item['starringCast'].split(',')
+ if item.has_key('director'):
+ infoLabels['Director'] = item['director']
+ if item.has_key('genres'):
+ infoLabels['Genre'] = ' / '.join(item['genres']).replace('_', ' & ').replace('Musikfilm & Tanz', 'Musikfilm, Tanz')
+ if item.has_key('customerReviewCollection'):
+ infoLabels['Rating'] = float(item['customerReviewCollection']['customerReviewSummary']['averageOverallRating'])*2
+ infoLabels['Votes'] = str(item['customerReviewCollection']['customerReviewSummary']['totalReviewCount'])
+ elif item.has_key('amazonRating'):
+ if item['amazonRating'].has_key('rating'): infoLabels['Rating'] = float(item['amazonRating']['rating'])*2
+ if item['amazonRating'].has_key('count'): infoLabels['Votes'] = str(item['amazonRating']['count'])
+ if item.has_key('heroUrl'):
+ infoLabels['Fanart'] = item['heroUrl']
+ if item.has_key('trailerAvailable'):
+ infoLabels['TrailerAvailable'] = item['trailerAvailable']
+ if item.has_key('runtime'):
+ infoLabels['Duration'] = str(item['runtime']['valueMillis']/1000)
+ if item.has_key('restrictions'):
+ for rest in item['restrictions']:
+ if rest['action'] == 'playback':
+ if rest['type'] == 'ageVerificationRequired': infoLabels['isAdult'] = 1
+
+ if contentType == 'series':
+ infoLabels['TVShowTitle'] = item['title']
+ if item.has_key('childTitles'):
+ infoLabels['TotalSeasons'] = item['childTitles'][0]['size']
+
+ elif contentType == 'season':
+ infoLabels['Season'] = item['number']
+ if item['ancestorTitles']:
+ try:
+ infoLabels['TVShowTitle'] = item['ancestorTitles'][0]['title']
+ infoLabels['SeriesAsin'] = item['ancestorTitles'][0]['titleId']
+ except: pass
+ else:
+ infoLabels['SeriesAsin'] = infoLabels['Asins'].split(',')[0]
+ infoLabels['TVShowTitle'] = item['title']
+ if item.has_key('childTitles'):
+ infoLabels['TotalSeasons'] = 1
+ infoLabels['Episode'] = item['childTitles'][0]['size']
+
+ elif contentType == 'episode':
+ if item.has_key('ancestorTitles'):
+ for content in item['ancestorTitles']:
+ if content['contentType'] == 'SERIES':
+ if content.has_key('titleId'): infoLabels['SeriesAsin'] = content['titleId']
+ if content.has_key('title'): infoLabels['TVShowTitle'] = content['title']
+ elif content['contentType'] == 'SEASON':
+ if content.has_key('number'): infoLabels['Season'] = content['number']
+ if content.has_key('titleId'): infoLabels['SeasonAsin'] = content['titleId']
+ if content.has_key('title'): seasontitle = content['title']
+ if not infoLabels['SeriesAsin']:
+ infoLabels['SeriesAsin'] = infoLabels['SeasonAsin']
+ infoLabels['TVShowTitle'] = seasontitle
+ if item.has_key('number'):
+ infoLabels['Episode'] = item['number']
+ infoLabels['DisplayTitle'] = '%s - %s' %(item['number'], infoLabels['Title'])
+ infoLabels = getArtWork(infoLabels, contentType)
+ if not infoLabels['Thumb']: infoLabels['Thumb'] = DefaultFanart
+ if not infoLabels['Fanart']: infoLabels['Fanart'] = DefaultFanart
+ return contentType, infoLabels
+
+def PlayVideo(name, asin, adultstr, trailer, selbitrate):
+ global amazonUrl
+ amazonUrl = BaseUrl + "/dp/" + asin
+ xbmc.Player().stop()
+
+ if trailer == '1':
+ if selPlugin == '':
+ PLAYTRAILER()
+ return
+ amazonUrl += "/?autoplaytrailer=1"
+ else:
+ if selPlugin == '':
+ PLAYVIDEOINT()
+ return
+ amazonUrl += "/?autoplay=1"
+ kiosk = 'yes'
+ if addon.getSetting("kiosk") == 'false': kiosk = 'no'
+
+ xbmc.executebuiltin('RunPlugin(plugin://%s/?url=%s&mode=showSite&kiosk=%s)' % (selPlugin, urllib.quote_plus(amazonUrl), kiosk))
+
+ pininput = 0
+ fullscr = 0
+ adult = int(adultstr)
+ if addon.getSetting("pininput") == 'true': pininput = 1
+ if addon.getSetting("fullscreen") == 'true': fullscr = 1
+
+ if adult == 1 and pininput == 1:
+ if fullscr == 1: waitsec = waitsec*0.75
+ else: waitsec = waitprepin
+ xbmc.sleep(int(waitsec))
+ Input(keys=pin)
+ if fullscr == 1: xbmc.sleep(waitpin)
+
+ if fullscr == 1:
+ xbmc.sleep(waitsec)
+ Input(mousex=-1,mousey=350)
+ if adult == 0: pininput = 1
+ if pininput == 1:
+ Input(mousex=-1,mousey=350,click=2)
+ xbmc.sleep(500)
+ Input(mousex=9999,mousey=350)
+
+def Input(mousex=0,mousey=0,click=0,keys=False,delay='200'):
+ if mousex == -1: mousex = screenWidth/2
+ if mousey == -1: mousey = screenHeight/2
+
+ if osWin:
+ app = userinput
+ mouse = ' mouse %s %s' % (mousex,mousey)
+ mclk = ' ' + str(click)
+ keybd = ' key %s{Enter} %s' % (keys,delay)
+ elif osLinux:
+ app = 'xdotool'
+ mouse = ' mousemove %s %s' % (mousex,mousey)
+ mclk = ' click --repeat %s 1' % click
+ keybd = ' type --delay %s %s && xdotool key Return' % (delay, keys)
+ elif osOsx:
+ app = 'cliclick'
+ mouse = ' m:'
+ if click == 1: mouse = ' c:'
+ elif click == 2: mouse = ' dc:'
+ mouse += '%s,%s' % (mousex,mousey)
+ mclk = ''
+ keybd = ' -w %s t:%s kp:return' % (delay, keys)
+
+ if keys:
+ cmd = app + keybd
+ else:
+ cmd = app + mouse
+ if click: cmd += mclk
+ Log('Run command: %s' % cmd)
+ subprocess.Popen(cmd, shell=True)
+
+def genID():
+ id = addon.getSetting("GenDeviceID")
+ if not id:
+ id = makeGUID()
+ addon.setSetting("GenDeviceID", id)
+ return id
+
+def MechanizeLogin():
+ cj = cookielib.LWPCookieJar()
+ if os.path.isfile(CookieFile):
+ cj.load(CookieFile, ignore_discard=True, ignore_expires=True)
+ return cj
+ Log('Login')
+ succeeded = LogIn()
+ retrys = 0
+ while succeeded == False:
+ xbmc.sleep(1000)
+ retrys += 1
+ Log('Login Retry: %s' % retrys)
+ succeeded = LogIn()
+ if retrys >= 2:
+ Dialog.ok('Login Error','Failed to Login')
+ succeeded=True
+ return succeeded
+
+def LogIn():
+ email = addon.getSetting('login_name')
+ password = decode(addon.getSetting('login_pass'))
+ changed = False
+
+ if addon.getSetting('save_login') == 'false' or email == '' or password == '':
+ keyboard = xbmc.Keyboard(addon.getSetting('login_name'), getString(30002))
+ keyboard.doModal()
+ if keyboard.isConfirmed() and keyboard.getText():
+ email = keyboard.getText()
+ password = setLoginPW()
+ if password: changed = True
+ if password:
+ if os.path.isfile(CookieFile):
+ os.remove(CookieFile)
+ cj = cookielib.LWPCookieJar()
+ br = mechanize.Browser()
+ br.set_handle_robots(False)
+ br.set_cookiejar(cj)
+ br.addheaders = [('User-agent', UserAgent)]
+ sign_in = br.open(BaseUrl + "/gp/aw/si.html")
+ br.select_form(name="signIn")
+ br["email"] = email
+ br["password"] = password
+ logged_in = br.submit()
+ error_str = "message error"
+ if error_str in logged_in.read():
+ Dialog.ok(getString(30200), getString(30201))
+ return False
+ else:
+ if addon.getSetting('save_login') == 'true' and changed:
+ addon.setSetting('login_name', email)
+ addon.setSetting('login_pass', encode(password))
+ if addon.getSetting('no_cookie') != 'true':
+ cj.save(CookieFile, ignore_discard=True, ignore_expires=True)
+ genID()
+ return cj
+ return True
+
+def setLoginPW():
+ keyboard = xbmc.Keyboard('', getString(30003), True)
+ keyboard.doModal()
+ if keyboard.isConfirmed() and keyboard.getText():
+ password = keyboard.getText()
+ return password
+ return False
+
+def encode(data):
+ k = triple_des((str(uuid.getnode())*2)[0:24], CBC, "\0\0\0\0\0\0\0\0", padmode=PAD_PKCS5)
+ d = k.encrypt(data)
+ return base64.b64encode(d)
+
+def decode(data):
+ if not data: return ''
+ k = triple_des((str(uuid.getnode())*2)[0:24], CBC, "\0\0\0\0\0\0\0\0", padmode=PAD_PKCS5)
+ d = k.decrypt(base64.b64decode(data))
+ return d
+
+def remLoginData():
+ if os.path.isfile(CookieFile):
+ os.remove(CookieFile)
+ addon.setSetting('login_name', '')
+ addon.setSetting('login_pass', '')
+
+def makeGUID():
+ import random
+ guid = ''
+ for i in range(3):
+ number = "%X" % (int( ( 1.0 + random.random() ) * 0x10000) | 0)
+ guid += number[1:]
+ return hmac.new(UserAgent, guid, hashlib.sha224).hexdigest()
+
+def scrapAsins(url):
+ asins = []
+ url = BaseUrl + url
+ content = getURL(url, useCookie=True)
+ asins += re.compile('data-asin="(.+?)"', re.DOTALL).findall(content)
+ return ','.join(asins)
+
+def createDB():
+ c = db.cursor()
+ c.execute('''CREATE TABLE art(
+ asin TEXT,
+ season INTEGER,
+ poster TEXT,
+ banner TEXT,
+ fanart TEXT,
+ lastac DATE,
+ PRIMARY KEY(asin, season)
+ );''')
+ db.commit()
+ c.close()
+
+def cleanName(name, file=True):
+ if file: notallowed = ['<', '>', ':', '"', '\\', '/', '|', '*', '?']
+ else:
+ notallowed = ['<', '>', '"', '|', '*', '?']
+ if not os.path.supports_unicode_filenames: name = name.encode('utf-8')
+ for c in notallowed:
+ name = name.replace(c,'')
+ return name
+
+def UpdateLibrary():
+ xbmc.executebuiltin('UpdateLibrary(video)')
+
+def SaveFile(filename, data, dir=False, mode='w'):
+ if type(data) == type(unicode()): data = data.encode('utf-8')
+ if dir:
+ filename = cleanName(filename)
+ filename = os.path.join(dir, filename)
+ filename = cleanName(filename, file=False)
+ file = open(filename, mode)
+ file.write(data)
+ file.close()
+
+def CreateDirectory(dir_path):
+ dir_path = cleanName(dir_path.strip(), file=False)
+ if not os.path.exists(dir_path):
+ os.makedirs(dir_path)
+ return True
+ return False
+
+def SetupLibrary():
+ CreateDirectory(MOVIE_PATH)
+ CreateDirectory(TV_SHOWS_PATH)
+ SetupAmazonLibrary()
+
+def CreateInfoFile(file, path, content, Info, language, hasSubtitles = False):
+ skip_keys = ('ishd', 'isadult', 'audiochannels', 'genre', 'cast', 'duration', 'asins', 'contentType')
+
+ fileinfo = ''
+ fileinfo += '<%s>' % content
+ if Info.has_key('Duration'):
+ fileinfo += '%s' % Info['Duration']
+ if Info.has_key('Genre'):
+ for genre in Info['Genre'].split('/'):
+ fileinfo += '%s' % genre.strip()
+ if Info.has_key('Cast'):
+ for actor in Info['Cast']:
+ fileinfo += ''
+ fileinfo += '%s' % actor.strip()
+ fileinfo += ''
+ for key, value in Info.items():
+ lkey = key.lower()
+ if lkey == 'tvshowtitle':
+ fileinfo += '%s' % value
+ elif lkey == 'premiered' and Info.has_key('TVShowTitle'):
+ fileinfo += '%s' % value
+ elif lkey == 'fanart':
+ fileinfo += '<%s>%s%s>' % (lkey, value, lkey)
+ elif lkey not in skip_keys:
+ fileinfo += '<%s>%s%s>' % (lkey, value, lkey)
+ if content != 'tvshow':
+ fileinfo += ''
+ fileinfo += ''
+ fileinfo += ''
+ fileinfo += ''
+ if hasSubtitles == True:
+ fileinfo += ''
+ fileinfo += 'ger'
+ fileinfo += ''
+ fileinfo += ''
+ fileinfo += ''
+ fileinfo += '%s>' % content
+
+ SaveFile(file + '.nfo', fileinfo, path)
+ return
+
+def SetupAmazonLibrary():
+ Log('Trying to add Amazon source paths...')
+ source_path = os.path.join(ProfilPath, 'sources.xml')
+ source_added = False
+
+ try:
+ file = open(source_path)
+ soup = BeautifulSoup(file)
+ file.close()
+ except:
+ subtags = ['programs', 'video', 'music', 'pictures', 'files']
+ soup = BeautifulSoup('')
+ root = soup.sources
+ for cat in subtags:
+ cat_tag = Tag(soup, cat)
+ def_tag = Tag(soup, 'default')
+ def_tag['pathversion'] = 1
+ cat_tag.append(def_tag)
+ root.append(cat_tag)
+
+ video = soup.find("video")
+
+ if len(soup.findAll(text="Amazon Movies")) < 1:
+ movie_source_tag = Tag(soup, "source")
+ movie_name_tag = Tag(soup, "name")
+ movie_name_tag.insert(0, "Amazon Movies")
+ movie_path_tag = Tag(soup, "path")
+ movie_path_tag['pathversion'] = 1
+ movie_path_tag.insert(0, MOVIE_PATH)
+ movie_source_tag.insert(0, movie_name_tag)
+ movie_source_tag.insert(1, movie_path_tag)
+ video.insert(2, movie_source_tag)
+ source_added = True
+
+ if len(soup.findAll(text="Amazon TV")) < 1:
+ tvshow_source_tag = Tag(soup, "source")
+ tvshow_name_tag = Tag(soup, "name")
+ tvshow_name_tag.insert(0, "Amazon TV")
+ tvshow_path_tag = Tag(soup, "path")
+ tvshow_path_tag['pathversion'] = 1
+ tvshow_path_tag.insert(0, TV_SHOWS_PATH)
+ tvshow_source_tag.insert(0, tvshow_name_tag)
+ tvshow_source_tag.insert(1, tvshow_path_tag)
+ video.insert(2, tvshow_source_tag)
+ source_added = True
+
+ if source_added:
+ Log('Source paths added!')
+ SaveFile(source_path, str(soup))
+ dialog.ok(getString(30187), getString(30188), getString(30189), getString(30190))
+ if dialog.yesno(getString(30191), getString(30192)):
+ xbmc.executebuiltin('RestartApp')
+
+dbFile = os.path.join(DataPath, 'art.db')
+if not os.path.exists(dbFile):
+ db = sqlite.connect(dbFile)
+ db.text_factory = str
+ createDB()
+else:
+ db = sqlite.connect(dbFile)
+ db.text_factory = str
+deviceID = genID()
+
+url = urlparse.urlparse(sys.argv[2])
+par = urlparse.parse_qsl(url.query)
+url = mode = opt = ''
+export = '0'
+page = '1'
+Log(par)
+for name, value in par: exec '%s = "%s"' % (name, value)
+
+if mode == 'listCategories': listCategories(url, opt)
+elif mode == 'listContent': listContent(cat, url, page, opt)
+elif mode == 'loadArtWork': loadArtWork(asins, title, year, ct)
+elif mode == 'PlayVideo': PlayVideo(name, asin, adult, trailer, selbitrate)
+elif mode == 'getList': getList(url, int(export))
+elif mode == 'WatchList': WatchList(url, int(opt))
+elif mode == '': MainMenu()
+else: exec mode + '()'
+
diff --git a/plugin.video.amazon-test/fanart.jpg b/plugin.video.amazon-test/fanart.jpg
new file mode 100644
index 00000000..e07f785e
Binary files /dev/null and b/plugin.video.amazon-test/fanart.jpg differ
diff --git a/plugin.video.amazon-test/icon.png b/plugin.video.amazon-test/icon.png
new file mode 100644
index 00000000..0b27fba8
Binary files /dev/null and b/plugin.video.amazon-test/icon.png differ
diff --git a/plugin.video.amazon-test/plugin.video.amazon-test-0.0.4.zip b/plugin.video.amazon-test/plugin.video.amazon-test-0.0.4.zip
new file mode 100644
index 00000000..a38b0418
Binary files /dev/null and b/plugin.video.amazon-test/plugin.video.amazon-test-0.0.4.zip differ
diff --git a/plugin.video.amazon-test/resources/__init__.py b/plugin.video.amazon-test/resources/__init__.py
new file mode 100644
index 00000000..b93054b3
--- /dev/null
+++ b/plugin.video.amazon-test/resources/__init__.py
@@ -0,0 +1 @@
+# Dummy file to make this directory a package.
diff --git a/plugin.video.amazon-test/resources/language/English/strings.xml b/plugin.video.amazon-test/resources/language/English/strings.xml
new file mode 100644
index 00000000..dff2f16b
--- /dev/null
+++ b/plugin.video.amazon-test/resources/language/English/strings.xml
@@ -0,0 +1,108 @@
+
+
+ Amazon Account
+ Email Adress
+ Password
+ Stream Bitrate (0 - Ask)
+ Enable Subtitles
+ Remember Credentials (unsecure)?
+ Remove Credentials and Cookie
+ Don't use Cookie
+
+ Choose Country
+ Germany
+ United Kingdom
+ USA
+ Japan
+
+ General
+ Playback with
+
+ Views
+ Movie Fanart Source
+ TV Show Fanart Source
+ Amazon
+ Load missing from TMDb
+ TMDb
+ Load missing from TVDb
+ TVDb
+ Show TV Show Fanart in Season and Episode Lists
+ TVDb incl. Poster
+
+ Thumbnail
+ Poster Wrap
+ List
+ Media Info 2
+ Media Info
+ Fanart
+ Big List
+ Custom
+
+ Enable Views
+ Movie View
+ Show View
+ Season View
+ Episode View
+
+ Update
+ Items Per Page
+
+ Switch Fullscreen
+ Browser Kiosk Mode
+ Wait for Fullscreen (sec)
+ Automatic PIN Input
+ PIN
+ Wait after PIN Input
+
+ Library
+ Custom Library Folder
+ Path
+
+ Toogle Watched State
+ Library
+ Movies
+ Television
+ Search
+ Choose Bitrate for Playback
+ Continue to Page %s
+ Back to Page %s
+ Choose Language for Playback
+ Choose Stream Quality:
+ Available Languages:
+
+ No content found
+
+ All Movies
+ All Shows
+
+ Movie
+ Show
+ Season
+ Year
+ Specials
+ Episode
+
+ Add %s to Watchlist
+ Remove %s from Watchlist
+ Go to TV-Show
+ Export %s
+
+ Update Library
+ Source folders added
+ To complete the setup:
+ 1) Restart Kodi
+ 2) Set the content type of added folders
+ Restart
+ Do you want to restart Kodi now?
+
+ Login Error
+ Wrong Email Adress or Password
+ No Search Results
+ Unable to Play
+ Invalid Request
+ Playback Limit reached, try again later
+ Product not purchased
+ This Video is unavailable in your Country
+ Playback currently not possible, try again later
+ Unknown
+
diff --git a/plugin.video.amazon-test/resources/language/German/strings.xml b/plugin.video.amazon-test/resources/language/German/strings.xml
new file mode 100644
index 00000000..7d943945
--- /dev/null
+++ b/plugin.video.amazon-test/resources/language/German/strings.xml
@@ -0,0 +1,116 @@
+
+
+ Amazon Zugangsdaten
+ E-Mail Adresse
+ Passwort
+ Stream Bitrate (0 - Fragen)
+ Untertitel aktivieren
+ Zugangsdaten speichern (unsicher)?
+ Keinen Cookie verwenden
+ Zugangsdaten und Cookie entfernen
+
+ Land auswählen
+ Deutschland
+ Großbritannien
+ USA
+ Japan
+
+ Allgemein
+ Wiedergabemethode
+
+ Ansicht
+ Film-Fanart Quelle
+ Serien-Fanart Quelle
+ Amazon
+ Fehlende von TMDb
+ Komplett von TMDb
+ Fehlende von TVDb
+ Komplett von TVDb
+ Serien-Fanart in der Staffel- und Episodenliste anzeigen
+ TVDb inkl. Poster
+
+ Vorschau
+ Poster Wrap
+ Liste
+ Media Info 2
+ Media Info
+ Fanart
+ Große Liste
+ Benutzerdefiniert
+
+ Ansichten aktivieren
+ Film Ansicht
+ Serien Ansicht
+ Staffel Ansicht
+ Episoden Ansicht
+
+ Verbindung
+ Elemente pro Seite
+
+ Vollbild aktivieren
+ Browser Kiosk Modus
+ Wartezeit für Vollbild (sek)
+ Automatische PIN Eingabe
+ PIN
+ Wartezeit nach PIN Eingabe
+ Browser Launcher konfigurieren...
+ Chrome Launcher konfigurieren...
+ Wartezeit bis PIN Eingabe
+
+ Bibliothek
+ Eigener Bibliothekordner
+ Pfad
+ Verschiedenes
+ Serie anstelle von Staffeln in der Watchlist anzeigen
+ Ausführliches Logging
+
+
+ Gesehen Status ändern
+ Bibliothek
+ Filme
+ Serien
+ Suchen
+ Bitrate auswählen und wiedergeben
+ Weiter zu Seite %s
+ Zurück zu Seite %s
+ Sprache auswählen und wiedergeben
+ Stream Qualität auswählen:
+ Verfügbare Sprachen:
+
+ Keine Inhalte gefunden
+
+ Alle Filme
+ Alle Serien
+
+ Film
+ Serie
+ Staffel
+ Jahr
+ Spezial
+ Episode
+
+ %s zur Watchlist hinzufügen
+ %s aus Watchlist entfernen
+ Zur Serie wechseln
+ %s exportieren
+
+ Bibliothek aktualisieren
+ Amazon Video-Quellen hinzugefügt
+ Zum Abschluß des Setups:
+ 1) XBMC/Kodi neustarten
+ 2) den Inhalt der Ordner festlegen
+ Neustart
+ Soll der XBMC/Kodi neugestartet werden?
+
+ Fehler bei der Anmeldung
+ E-Mail Adresse oder Passwort falsch
+ Keine Suchergebnisse
+ Wiedergabe nicht möglich
+ Anfrage fehlgeschlagen
+ Wiedergabelimit erreicht, später erneut versuchen
+ Produkt nicht erworben
+ Dieses Video ist in Ihren Land nicht verfügbar
+ Wiedergabe momentan nicht möglich, später erneut versuchen
+ Unbekannt
+ Bitte Zugangsdaten und Cookie in den Einstellungen löschen
+
diff --git a/plugin.video.amazon-test/resources/language/Polish/strings.xml b/plugin.video.amazon-test/resources/language/Polish/strings.xml
new file mode 100644
index 00000000..3a332e01
--- /dev/null
+++ b/plugin.video.amazon-test/resources/language/Polish/strings.xml
@@ -0,0 +1,101 @@
+
+
+ Logowanie do Amazon Prime Instant Video
+ Email
+ Hasło
+ Stream bitrate (0 - pytanie)
+ Aktywuj napisy
+ Zapisać dane logowania (niebezpieczne)?
+ Usuń dane logowania i cookies
+
+ Ogólne
+ Odtwarzanie
+
+ Wyświetlanie
+ Pobieraj brakujący Fanart przez TMDB (w tle)
+ Pobieraj brakujący Fanart TV przez TVDB (w tle)
+
+ Podgląd
+ Plakat
+ Lista
+ Tablica info 2
+ Tablica info
+ Fanart
+ Duża lista
+
+ Aktywuj zasady wyświetlania mediów
+ Wyświetlaj filmy
+ Wyświetlaj seriale
+ Wyświetlaj sezony
+ Wyświetlaj epizody
+ Zdefiniowane przez użytkownika
+
+ Logowanie i dane
+ Ilość elementów na stronie
+
+ Aktywuj tryb pełnoekranowy
+ Tryb przeglądarki Kiosk
+ Jeśli możliwe, to odtwarzaj w jakości HD
+ Oczekiwanie na tryb pełnoekranowy (w sek.)
+ Automatyczne wpisanie PIN
+ PIN
+ Oczekiwanie po wpisaniu PIN
+
+ Amazon
+ Brakujące z TMDb
+ Kompletne z TMDb
+ Brakujące z TVDb
+ Kompletne z TVDb
+ Pokazuj Fanart serialu w liście sezonów i epizodów
+ TVDb w tym Plakat
+
+ Biblioteka
+ Własny folder biblioteki
+ Ścieżka
+
+ Biblioteka
+ Filmy
+ Seriale
+ Szukaj
+ Wybierz jakość i odtwarzaj
+ Dalej %s
+ Wróć %s
+ Wybierz język i odtwarzaj
+ Wybierz jakość streamu:
+ Dostępne języki:
+
+ Brak nowych danych
+
+ Wszystkie
+ Wszystkie
+
+ Film
+ Serial
+ Sezon
+ Rok
+ Specjalne
+ Epizod
+
+ Dodaj %s do watchlist
+ Usuń %s z watchlist
+ Dodaj %s do biblioteki
+
+ Aktualizuj bibliotekę
+ Źródła Amazon Video dodane
+ Po zakończeniu konfigurowania:
+ 1) Uruchom ponownie XBMC/Kodi
+ 2) Ustal zawartość katalogów
+ Uruchom ponownie
+ Uruchomić ponownie XBMC/Kodi?
+
+ Błąd w trakcie logowania
+ Błędny adres email lub hasło
+ Brak wyników wyszukiwania
+ Odtwarzanie niemożliwe
+ Zapytanie zakończone niepowodzeniem
+ Osiągnięto limit odtwarzania, proszę spróbować później
+ Produkt nie został nabyty
+ To wideo nie jest dostępne w Twoim kraju
+ Odtwarzanie jest teraz niemożliwe, spróbuj ponownie później
+ Nieznane:
+
diff --git a/plugin.video.amazon-test/resources/settings.xml b/plugin.video.amazon-test/resources/settings.xml
new file mode 100644
index 00000000..b7aacd67
--- /dev/null
+++ b/plugin.video.amazon-test/resources/settings.xml
@@ -0,0 +1,50 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/plugin.video.amazon-test/tools/userinput.exe b/plugin.video.amazon-test/tools/userinput.exe
new file mode 100644
index 00000000..65c9c751
Binary files /dev/null and b/plugin.video.amazon-test/tools/userinput.exe differ
diff --git a/plugin.video.amazon/addon.xml b/plugin.video.amazon/addon.xml
index 063ef11d..231877a1 100644
--- a/plugin.video.amazon/addon.xml
+++ b/plugin.video.amazon/addon.xml
@@ -9,6 +9,7 @@
+
diff --git a/plugin.video.amazon/plugin.video.amazon-1.4.8.zip b/plugin.video.amazon/plugin.video.amazon-1.4.8.zip
index b3781509..3f05ea31 100644
Binary files a/plugin.video.amazon/plugin.video.amazon-1.4.8.zip and b/plugin.video.amazon/plugin.video.amazon-1.4.8.zip differ
diff --git a/plugin.video.amazon/resources/lib/play.py b/plugin.video.amazon/resources/lib/play.py
index 1c867c4d..27267b31 100644
--- a/plugin.video.amazon/resources/lib/play.py
+++ b/plugin.video.amazon/resources/lib/play.py
@@ -35,7 +35,7 @@
osWin = xbmc.getCondVisibility('system.platform.windows')
screenWidth = int(xbmc.getInfoLabel('System.ScreenWidth'))
screenHeight = int(xbmc.getInfoLabel('System.ScreenHeight'))
-playPlugin = ['','plugin.program.browser.launcher', 'plugin.program.chrome.launcher']
+playPlugin = ['plugin.program.browser.launcher', 'plugin.program.chrome.launcher']
selPlugin = playPlugin[int(settings.getSetting("playmethod"))]
StrProt = int(settings.getSetting("protocol"))
trailer = common.args.trailer
diff --git a/plugin.video.amazon/resources/settings.xml b/plugin.video.amazon/resources/settings.xml
index 4686ff0e..e5f34fa5 100644
--- a/plugin.video.amazon/resources/settings.xml
+++ b/plugin.video.amazon/resources/settings.xml
@@ -1,7 +1,7 @@
-
+
diff --git a/script.module.pydes/addon.xml b/script.module.pydes/addon.xml
new file mode 100644
index 00000000..a4b3f077
--- /dev/null
+++ b/script.module.pydes/addon.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+ A pure python module which implements the DES and Triple-DES encryption algorithms.
+ http://twhiteman.netfirms.com/des.html
+ Public Domain
+ all
+
+
+
diff --git a/plugin.video.amazon/resources/lib/pyDes.py b/script.module.pydes/lib/pyDes.py
similarity index 100%
rename from plugin.video.amazon/resources/lib/pyDes.py
rename to script.module.pydes/lib/pyDes.py
diff --git a/script.module.pydes/script.module.pydes-2.0.1.zip b/script.module.pydes/script.module.pydes-2.0.1.zip
new file mode 100644
index 00000000..cba45711
Binary files /dev/null and b/script.module.pydes/script.module.pydes-2.0.1.zip differ