diff --git a/plugin.video.prime_instant/addon.xml b/plugin.video.prime_instant/addon.xml index fc7b161..8d109ec 100644 --- a/plugin.video.prime_instant/addon.xml +++ b/plugin.video.prime_instant/addon.xml @@ -1,5 +1,5 @@ - + @@ -14,7 +14,7 @@ Amazon Prime Instant Video Add-on (US/UK/DE) Some parts of this addon may not be legal in your country of residence - please check with your local laws before installing. GNU GENERAL PUBLIC LICENSE. Version 2, June 1991 - https://github.com/XLordKX/kodi + https://github.com/AddonScriptorDE/plugin.video.prime_instant http://www.kodinerds.net/index.php/Thread/43912-RELEASE-Amazon-Prime-Instant-Video-US-UK-DE/ http://www.amazon.com diff --git a/plugin.video.prime_instant/changelog.txt b/plugin.video.prime_instant/changelog.txt index 2b015f9..6265021 100644 --- a/plugin.video.prime_instant/changelog.txt +++ b/plugin.video.prime_instant/changelog.txt @@ -1,12 +1,31 @@ -1.0.3 -- Forked from AddonScriptorDE Repository -- Bug fixes -- Added translations for some dialogs +1.0.0 +- Initial release +1.0.1 +- Changed login (email and password are not stored anymore) 1.0.2 - Added debug output - Fixed folder encoding issue - Some small improvements -1.0.1 -- Changed login (email and password are not stored anymore) -1.0.0 -- Initial release +1.0.2-r1 +- Added end soon section +1.0.2-r2 +- Fixed encoding of the watchlist +1.0.2-r7 +- Fix for new site version to play videos +1.0.2-r8 +- Fix for video information +1.0.2-r9 +- Fix watchlist for new site version +1.0.2-r11 +- Merge with syscrashs version + * Watchlist korrigiert + * Filminfos korrigiert + * csrfToken korrigiert +1.0.2-r12 +- Fix detail-Bug with umlauts +1.0.2-r13 +- Remove whitespaces in episode description +1.0.2-r15 +- merge with https://github.com/XLordKX/kodi commit 171bb377fe +1.0.2-r16 +- add snd watchlist format diff --git a/plugin.video.prime_instant/default.py b/plugin.video.prime_instant/default.py index fb28a58..8990907 100644 --- a/plugin.video.prime_instant/default.py +++ b/plugin.video.prime_instant/default.py @@ -53,6 +53,7 @@ def translation(id): showNotification = addon.getSetting("showNotification") == "true" showOriginals = addon.getSetting("showOriginals") == "true" showLibrary = addon.getSetting("showLibrary") == "true" +showAvailability = addon.getSetting("showAvailability") == "true" showKids = addon.getSetting("showKids") == "true" forceView = addon.getSetting("forceView") == "true" updateDB = addon.getSetting("updateDB") == "true" @@ -77,12 +78,9 @@ def translation(id): addon.setSetting('email', '') addon.setSetting('password', '') - opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cj)) -userAgent = "Mozilla/5.0 (X11; U; Linux i686; en-EN) AppleWebKit/533.4 (KHTML, like Gecko) Chrome/5.0.375.127 Large Screen Safari/533.4 GoogleTV/ 162671" -#userAgent = "Mozilla/5.0 (Windows NT 6.3; WOW64; rv:35.0) Gecko/20100101 Firefox/35.0" +userAgent = "Mozilla/5.0 (X11; U; Linux i686; en-US) AppleWebKit/533.4 (KHTML, like Gecko) Chrome/5.0.375.127 Large Screen Safari/533.4 GoogleTV/ 162671" opener.addheaders = [('User-agent', userAgent)] -deviceTypeID = "A324MFXUEZFF7B" if not os.path.isdir(addonUserDataFolder): os.mkdir(addonUserDataFolder) @@ -102,7 +100,6 @@ def translation(id): cj.load(cookieFile) - def index(): loginResult = login() if loginResult=="prime": @@ -127,6 +124,7 @@ def browseMovies(): addDir(translation(30007), urlMain+"/gp/search/ajax/?rh=n%3A3010075031%2Cn%3A!3010076031%2Cn%3A3015915031%2Cp_n_theme_browse-bin%3A3015972031%2Cp_85%3A3282148031&ie=UTF8", 'listMovies', "") addDir(translation(30008), urlMain+"/gp/search/ajax/?_encoding=UTF8&rh=n%3A3279204031%2Cn%3A!3010076031%2Cn%3A3356018031&sort=date-desc-rank", 'listMovies', "") addDir(translation(30009), urlMain+"/s/?n=4963842031", 'listMovies', "") + addDir(translation(30999), urlMain+"/gp/search/ajax/?_encoding=UTF8&rh=n%3A3010075031%2Cn%3A3356018031%2Cn%3A4225009031&sort=popularity-rank", 'listMovies', "") elif siteVersion=="com": addDir(translation(30006), urlMain+"/gp/search/ajax/?_encoding=UTF8&rh=n%3A2858778011%2Cn%3A7613704011&sort=popularity-rank", 'listMovies', "") addDir(translation(30011), urlMain+"/gp/search/other/?rh=n%3A2676882011%2Cn%3A7613704011&pickerToList=theme_browse-bin&ie=UTF8", 'listGenres', "", "movie") @@ -158,6 +156,7 @@ def browseTV(): addDir(translation(30007), urlMain+"/gp/search/ajax/?rh=n%3A3010075031%2Cn%3A!3010076031%2Cn%3A3015916031%2Cp_n_theme_browse-bin%3A3015972031%2Cp_85%3A3282148031&ie=UTF8", 'listShows', "") addDir(translation(30010), urlMain+"/gp/search/ajax/?_encoding=UTF8&keywords=[OV]&rh=n%3A3010075031%2Cn%3A3015916031%2Ck%3A[OV]%2Cp_85%3A3282148031&sort=date-desc-rank", 'listShows', "") addDir(translation(30008), urlMain+"/gp/search/ajax/?_encoding=UTF8&rh=n%3A3279204031%2Cn%3A3010075031%2Cn%3A3015916031&sort=date-desc-rank", 'listShows', "") + addDir(translation(30999), urlMain+"/gp/search/ajax/?_encoding=UTF8&rh=n%3A3010075031%2Cn%3A3356019031%2Cn%3A4225009031&sort=popularity-rank", 'listShows', "") elif siteVersion=="com": addDir(translation(30006), urlMain+"/gp/search/ajax/?_encoding=UTF8&rh=n%3A2858778011%2Cn%3A7613705011&sort=popularity-rank", 'listShows', "") addDir(translation(30011), urlMain+"/gp/search/other/?rh=n%3A2676882011%2Cn%3A7613705011&pickerToList=theme_browse-bin&ie=UTF8", 'listGenres', "", "tv") @@ -214,7 +213,7 @@ def listOriginals(): elif siteVersion=="co.uk": content = opener.open(urlMain+"/b/?ie=UTF8&node=5687760031").read() debug(content) - match = re.compile("token : '(.+?)'", re.DOTALL).findall(content) + match = re.compile('csrf":"(.+?)"', re.DOTALL).findall(content) if match: addon.setSetting('csrfToken', match[0]) content = content[content.find('', re.DOTALL).findall(entry) + if match: + index=entry.find(match[0])+len(match[0]) + entry=entry[index:] + depth=1 + element=match[0] + + while depth > 0: + match=re.compile('^.*?\', re.DOTALL).findall(entry) + matchend=re.compile('^.*?\<\/div\>', re.DOTALL).findall(match[0]) + if matchend: + entry=entry[len(matchend[0]):] + depth=depth-1 + element+=matchend[0] + else: + entry=entry[len(match[0]):] + depth=depth+1 + element+=match[0] + elements.append(element) + else: + break + dlParams = [] - videoType = "" - showEntries = [] + for entry in elements: + if "/library/" in url or ("/watchlist/" in url and ("class='prime-meta'" in entry or 'class="prime-logo"' in entry or "class='item-green'" in entry or 'class="packshot-sash' in entry)): + match = re.compile('data-prod-type="(.+?)"', re.DOTALL).findall(entry) + if match: + if match[0] == "downloadable_tv_season": + videoType = "tv" + else: + videoType = "movie" + match = re.compile('id="(.+?)"', re.DOTALL).findall(entry) + videoID = match[0] + match = re.compile('title="(.+?)"', re.DOTALL).findall(entry) + title = match[0] + avail='' + if showAvailability: + match = re.compile('\(.+?)\<\/span\>', re.DOTALL).findall(entry) + if match: + avail=" - " + cleanInput(match[0]) + title = cleanTitle(title)+avail + if videoType=="tv": + title = cleanSeasonTitle(title)+avail + if title in showEntries: + continue + showEntries.append(title) + match = re.compile('src="(.+?)"', re.DOTALL).findall(entry) + thumbUrl = "" + if match: + thumbUrl = match[0].replace(".jpg", "") + thumbUrl = thumbUrl[:thumbUrl.rfind(".")]+".jpg" + dlParams.append({'type':videoType, 'id':videoID, 'title':cleanTitleTMDB(cleanSeasonTitle(title)), 'thumb':thumbUrl, 'year':''}) + + return dlParams + +def parseWatchListOld(content): + dlParams = [] + spl = content.split('
')] - if "/library/" in url or ("/watchlist/" in url and ("class='prime-meta'" in entry or 'class="prime-logo"' in entry)): + if "/library/" in url or ("/watchlist/" in url and ("class='prime-meta'" in entry or 'class="prime-logo"' in entry or "class='item-green'" in entry or 'class="packshot-sash' in entry)): match = re.compile('data-prod-type="(.+?)"', re.DOTALL).findall(entry) if match: videoType = match[0] @@ -280,7 +336,6 @@ def listWatchList(url): match = re.compile('title="(.+?)"', re.DOTALL).findall(entry) title = match[0] title = cleanTitle(title) - dlParams.append({'type':videoType, 'id':videoID, 'title':cleanTitleTMDB(cleanSeasonTitle(title)), 'year':''}) if videoType=="tv": title = cleanSeasonTitle(title) if title in showEntries: @@ -291,19 +346,40 @@ def listWatchList(url): if match: thumbUrl = match[0].replace(".jpg", "") thumbUrl = thumbUrl[:thumbUrl.rfind(".")]+".jpg" - if videoType == "movie": - addLinkR(title, videoID, "playVideo", thumbUrl, videoType) - else: - addShowDirR(title, videoID, "listSeasons", thumbUrl, videoType) + dlParams.append({'type':videoType, 'id':videoID, 'title':cleanTitleTMDB(cleanSeasonTitle(title)), 'thumb':thumbUrl, 'year':''}) + return dlParams + + +def listWatchList(url): + content = opener.open(url).read() + debug(content) + match = re.compile('csrf":"(.+?)"', re.DOTALL).findall(content) + if match: + addon.setSetting('csrfToken', match[0]) + + dlParams = [] + if "grid-list-item" in content: + dlParams = parseWatchListNew(content) + else: + dlParams = parseWatchListOld(content) + + videoType = "" + for entry in dlParams: + videoType = entry['type'] + if entry['type'] == "movie": + addLinkR(entry['title'], entry['id'], "playVideo", entry['thumb'], entry['type']) + else: + addShowDirR(entry['title'], entry['id'], "playVideo", entry['thumb'], entry['type']) + if videoType == "movie": xbmcplugin.setContent(pluginhandle, "movies") else: xbmcplugin.setContent(pluginhandle, "tvshows") if useTMDb and videoType == "movie": - dlParams = json.dumps(dlParams) + dlParams = json.dumps(unicode(dlParams)) xbmc.executebuiltin('XBMC.RunScript('+downloadScript+', '+urllib.quote_plus(str(dlParams))+')') elif useTMDb: - dlParams = json.dumps(dlParams) + dlParams = json.dumps(unicode(dlParams)) xbmc.executebuiltin('XBMC.RunScript('+downloadScriptTV+', '+urllib.quote_plus(str(dlParams))+')') xbmcplugin.endOfDirectory(pluginhandle) xbmc.sleep(100) @@ -321,11 +397,16 @@ def listMovies(url): content = content.replace("\\","") if 'id="catCorResults"' in content: content = content[:content.find('id="catCorResults"')] - match = re.compile('"csrfToken":"(.+?)"', re.DOTALL).findall(content) + match = re.compile('csrf":"(.+?)"', re.DOTALL).findall(content) if match: addon.setSetting('csrfToken', match[0]) spl = content.split('id="result_') dlParams = [] + match = re.compile('\<\/span\>(\.+?\<\/a\>)', re.DOTALL).findall(content) + if match: + textMatch=re.compile('\>(.+?)\<', re.DOTALL).findall(match[0]) + linkMatch=re.compile('href="(.+?)"\>', re.DOTALL).findall(match[0]) + addDir(textMatch[0], urlMain+linkMatch[0].replace("&","&"), "listMovies", "DefaultTVShows.png") for i in range(1, len(spl), 1): entry = spl[i] match = re.compile('asin="(.+?)"', re.DOTALL).findall(entry) @@ -356,7 +437,7 @@ def listMovies(url): else: addLink(title, videoID, "playVideo", thumbUrl, "movie", "", "", year) if useTMDb: - dlParams = json.dumps(unicode(dlParams)) + dlParams = json.dumps(dlParams) xbmc.executebuiltin('XBMC.RunScript('+downloadScript+', '+urllib.quote_plus(str(dlParams))+')') match = re.compile('class="pagnNext".*?href="(.+?)"', re.DOTALL).findall(content) if match: @@ -429,7 +510,7 @@ def listSimilarMovies(videoID): xbmcplugin.setContent(pluginhandle, "movies") content = opener.open(urlMain+"/gp/product/"+videoID).read() debug(content) - match = re.compile("token : '(.+?)'", re.DOTALL).findall(content) + match = re.compile('csrf":"(.+?)"', re.DOTALL).findall(content) if match: addon.setSetting('csrfToken', match[0]) spl = content.split('
  • ')] match = re.compile('class="episode-title">(.+?)<', re.DOTALL).findall(entry) - if match and ('class="prime-logo-small"' in entry or 'class="episode-status cell-free"' in entry): + if match and ('class="prime-logo-small"' in entry or 'class="episode-status cell-free"' in entry or 'class="episode-status cell-owned"' in entry): title = match[0] title = cleanTitle(title) episodeNr = title[:title.find('.')] title = title[title.find('.')+1:].strip() match = re.compile('/(.+?)/', re.DOTALL).findall(entry) episodeID = match[0] - match = re.compile('

    .+?(.+?)

    ', re.DOTALL).findall(entry) + match = re.compile('

    .+?\s*(.+?)\s*

    ', re.DOTALL).findall(entry) desc = "" if match: desc = cleanTitle(match[0]) @@ -583,7 +667,7 @@ def listEpisodes(seriesID, seasonID, thumb, content="", seriesName=""): percentage = match[0] if int(percentage)>95: playcount = 1 - addEpisodeLink(title, episodeID, 'playVideo', thumb, desc, length, matchSeason[0], episodeNr, seriesID, playcount, aired, seriesName) + addEpisodeLink(title, episodeID, 'playVideo', thumb, desc, length, seasonNr, episodeNr, seriesID, playcount, aired, seriesName) xbmcplugin.endOfDirectory(pluginhandle) xbmc.sleep(100) if forceView: @@ -629,18 +713,19 @@ def playVideo(videoID, selectQuality=False, playTrailer=False): if matchCID: matchSWFUrl=re.compile('', re.DOTALL).findall(content) + + match=re.compile('\[\ \t]*(.+?)[\ \t]*\<\/script\>', re.DOTALL).findall(content) jsonstr=cleanInput(match[0]) parsed=json.loads(jsonstr) title = parsed["name"] @@ -758,12 +844,9 @@ def showInfo(videoID): year = match[0] title = title+" ("+year+")" title = cleanTitle(title) - thumb = parsed["thumbnailUrl"].replace(".jpg", "") thumb = thumb[:thumb.rfind(".")]+".jpg" - director = parsed["director"][0]["name"].replace(",",", ") - actors = parsed["actor"][0]["name"].replace(",",", ") match=re.compile('property="og:duration" content="(.+?)"', re.DOTALL).findall(content) length = str(int(match[0])/60)+" min." @@ -848,7 +931,7 @@ def login(): keyboard.doModal() if keyboard.isConfirmed() and keyboard.getText(): email = keyboard.getText() - keyboard = xbmc.Keyboard('', translation(30091)) + keyboard = xbmc.Keyboard('', translation(30091), True) keyboard.doModal() if keyboard.isConfirmed() and keyboard.getText(): password = keyboard.getText() @@ -871,12 +954,52 @@ def login(): return "none" +def cleanInput(str): + + str = str.replace("&","&").replace("'","'").replace("é","é").replace("ä","ä").replace("ö","ö").replace("ü","ü").replace("Ä","Ä").replace("Ö","Ö").replace("Ü","Ü").replace("ß","ß").replace("…","…") + str = str.replace("é","é").replace("ä","ä").replace("ö","ö").replace("ü","ü").replace("Ä","Ä").replace("Ö","Ö").replace("Ü","Ü").replace("ß","ß") + printable=string.printable+"éäöüÄÖÜß…" + newStr='' + lastByte='\xff' + for c in str: + if c == '\xe4' or ( lastByte == '\x00' and c == '\xe4' ) or ( lastByte == '\xc3' and c == '\xa4'): + newStr+='ä' + lastByte=c + elif c == '\xf6' or ( lastByte == '\x00' and c == '\xf6' ) or ( lastByte == '\xc3' and c == '\xb6'): + newStr+='ö' + lastByte=c + elif c == '\xfc' or ( lastByte == '\x00' and c == '\xfc' ) or ( lastByte == '\xc3' and c == '\xbc') or ( lastByte == '\xc3' and ( c != '\xa4' and c != '\xb6' and c != '\x84' and c != '\x69' and c != '\x9c' and c != '\x9f' and c != '\xa9' ) ): + newStr+='ü' + lastByte=c + elif c == '\xc4' or ( lastByte == '\x00' and c == '\xc4' ) or ( lastByte == '\xc3' and c == '\x84'): + newStr+='Ä' + lastByte=c + elif c == '\xd6' or ( lastByte == '\x00' and c == '\xd6' ) or ( lastByte == '\xc3' and c == '\x69'): + newStr+='Ö' + lastByte=c + elif c == '\xdc' or ( lastByte == '\x00' and c == '\xdc' ) or ( lastByte == '\xc3' and c == '\x9c'): + newStr+='Ü' + lastByte=c + elif c == '\xdf' or ( lastByte == '\x00' and c == '\xdf' ) or ( lastByte == '\xc3' and c == '\x9f'): + newStr+='ß' + lastByte=c + elif c == '\xe9' or ( lastByte == '\x00' and c == '\xe9' ) or ( lastByte == '\xc3' and c == '\xa9'): + newStr+='é' + lastByte=c + elif c == '\x00' or c == '\xc3': + lastByte=c + else: + newStr+=c + lastByte=c + + newStr = filter(lambda c: c in printable, newStr) + return newStr + + def cleanTitle(title): if "[HD]" in title: title = title[:title.find("[HD]")] - title = title.replace("&","&").replace("'","'").replace("é","é").replace("ä","ä").replace("ö","ö").replace("ü","ü").replace("Ä","Ä").replace("Ö","Ö").replace("Ü","Ü").replace("ß","ß").replace("…","…") - title = title.replace("é","é").replace("ä","ä").replace("ö","ö").replace("ü","ü").replace("Ä","Ä").replace("Ö","Ö").replace("Ü","Ü").replace("ß","ß") - return title.replace("\xe4","ä").replace("\xf6","ö").replace("\xfc","ü").replace("\xc4","Ä").replace("\xd6","Ö").replace("\xdc","Ü").replace("\xdf","ß").strip() + return cleanInput(title) def cleanSeasonTitle(title): diff --git a/plugin.video.prime_instant/resources/language/English/strings.xml b/plugin.video.prime_instant/resources/language/English/strings.xml index 929ee7f..3c66190 100644 --- a/plugin.video.prime_instant/resources/language/English/strings.xml +++ b/plugin.video.prime_instant/resources/language/English/strings.xml @@ -77,4 +77,6 @@ General Views Advanced + Show availability + Deleted soon on prime instant video diff --git a/plugin.video.prime_instant/resources/language/German/strings.xml b/plugin.video.prime_instant/resources/language/German/strings.xml index 62786ee..a9be113 100644 --- a/plugin.video.prime_instant/resources/language/German/strings.xml +++ b/plugin.video.prime_instant/resources/language/German/strings.xml @@ -77,4 +77,6 @@ Allgemein Ansichten Erweitert + Verfügbarkeit anzeigen + Nur noch begrenzte Zeit bei Prime Instant Video diff --git a/plugin.video.prime_instant/resources/settings.xml b/plugin.video.prime_instant/resources/settings.xml index 1c9c257..c64229b 100644 --- a/plugin.video.prime_instant/resources/settings.xml +++ b/plugin.video.prime_instant/resources/settings.xml @@ -21,6 +21,7 @@ +