Advertisement
Guest User

Untitled

a guest
Oct 20th, 2015
2,642
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 66.00 KB | None | 0 0
  1. #!/usr/bin/python
  2. # -*- coding: utf-8 -*-
  3. import os
  4. import sys
  5. import re
  6. import json
  7. import time
  8. import shutil
  9. import threading
  10. import subprocess
  11. import xbmc
  12. import xbmcplugin
  13. import xbmcgui
  14. import xbmcaddon
  15. import xbmcvfs
  16. from resources.lib import chrome_cookies
  17.  
  18. trace_on = False
  19. addon = xbmcaddon.Addon()
  20.  
  21. if addon.getSetting("sslEnable") == "true":
  22. try:
  23. # Add support for newer SSL connections in requests
  24. # Ensure OpenSSL is installed with system package manager on linux
  25. import resources
  26. sys.path.append(os.path.dirname(resources.lib.__file__))
  27. import resources.lib.pyOpenSSL
  28. import OpenSSL
  29. # https://urllib3.readthedocs.org/en/latest/security.html#openssl-pyopenssl
  30. import requests.packages.urllib3.contrib.pyopenssl
  31. requests.packages.urllib3.contrib.pyopenssl.inject_into_urllib3()
  32. verify_ssl = True
  33. except Exception as ex:
  34. import traceback
  35. print traceback.format_exc()
  36. print "ERROR importing OpenSSL handler"
  37. verify_ssl = False
  38.  
  39. import requests
  40. import HTMLParser
  41. import urllib
  42. import socket
  43.  
  44. if addon.getSetting("sslEnable") == "false":
  45. verify_ssl = False
  46. print "SSL is Disabled"
  47. #supress warnings
  48. from requests.packages.urllib3.exceptions import InsecureRequestWarning
  49. from requests.packages.urllib3.exceptions import InsecurePlatformWarning
  50. requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
  51. requests.packages.urllib3.disable_warnings(InsecurePlatformWarning)
  52.  
  53. try:
  54. import cPickle as pickle
  55. except ImportError:
  56. import pickle
  57.  
  58. socket.setdefaulttimeout(40)
  59. pluginhandle = int(sys.argv[1])
  60.  
  61. while (addon.getSetting("username") == "" or addon.getSetting("password") == ""):
  62. addon.openSettings()
  63.  
  64. htmlParser = HTMLParser.HTMLParser()
  65. addonID = addon.getAddonInfo('id')
  66. osWin = xbmc.getCondVisibility('system.platform.windows')
  67. osLinux = xbmc.getCondVisibility('system.platform.linux')
  68. osOSX = xbmc.getCondVisibility('system.platform.osx')
  69. osAndroid = xbmc.getCondVisibility('system.platform.android')
  70. addonDir = xbmc.translatePath(addon.getAddonInfo('path'))
  71. defaultFanart = os.path.join(addonDir ,'fanart.png')
  72. addonUserDataFolder = xbmc.translatePath("special://profile/addon_data/"+addonID)
  73. icon = xbmc.translatePath('special://home/addons/'+addonID+'/icon.png')
  74. utilityPath = xbmc.translatePath('special://home/addons/'+addonID+'/resources/NetfliXBMC_Utility.exe')
  75. sendKeysPath = xbmc.translatePath('special://home/addons/'+addonID+'/resources/NetfliXBMC_SendKeys.exe')
  76. fakeVidPath = xbmc.translatePath('special://home/addons/'+addonID+'/resources/fakeVid.mp4')
  77. downloadScript = xbmc.translatePath('special://home/addons/'+addonID+'/download.py')
  78. browserScript = xbmc.translatePath('special://home/addons/'+addonID+'/browser.sh')
  79. searchHistoryFolder = os.path.join(addonUserDataFolder, "history")
  80. cacheFolder = os.path.join(addonUserDataFolder, "cache")
  81. cacheFolderCoversTMDB = os.path.join(cacheFolder, "covers")
  82. cacheFolderFanartTMDB = os.path.join(cacheFolder, "fanart")
  83. libraryFolder = xbmc.translatePath(addon.getSetting("libraryPath"))
  84. libraryFolderMovies = os.path.join(libraryFolder, "Movies")
  85. libraryFolderTV = os.path.join(libraryFolder, "TV")
  86. cookieFile = xbmc.translatePath("special://profile/addon_data/"+addonID+"/cookies")
  87. sessionFile = xbmc.translatePath("special://profile/addon_data/"+addonID+"/session")
  88. chromeUserDataFolder = os.path.join(addonUserDataFolder, "chrome-user-data")
  89. dontUseKiosk = addon.getSetting("dontUseKiosk") == "true"
  90. browseTvShows = addon.getSetting("browseTvShows") == "true"
  91. singleProfile = addon.getSetting("singleProfile") == "true"
  92. isKidsProfile = addon.getSetting('isKidsProfile') == 'true'
  93. showProfiles = addon.getSetting("showProfiles") == "true"
  94. forceView = addon.getSetting("forceView") == "true"
  95. useUtility = addon.getSetting("useUtility") == "true"
  96. useChromeProfile = addon.getSetting("useChromeProfile") == "true"
  97. remoteControl = addon.getSetting("remoteControl") == "true"
  98. updateDB = addon.getSetting("updateDB") == "true"
  99. useTMDb = addon.getSetting("useTMDb") == "true"
  100. username = addon.getSetting("username")
  101. password = addon.getSetting("password")
  102. viewIdVideos = addon.getSetting("viewIdVideos")
  103. viewIdEpisodes = addon.getSetting("viewIdEpisodesNew")
  104. viewIdActivity = addon.getSetting("viewIdActivity")
  105. winBrowser = int(addon.getSetting("winBrowserNew"))
  106. language = addon.getSetting("language")
  107. auth = addon.getSetting("auth")
  108. authMyList = addon.getSetting("authMyList")
  109. linuxUseShellScript = addon.getSetting("linuxUseShellScript") == "true"
  110. debug = addon.getSetting("debug") == "true"
  111.  
  112. country = addon.getSetting("country")
  113. if len(country)==0 and len(language.split("-"))>1:
  114. country = language.split("-")[1]
  115.  
  116. from requests.adapters import HTTPAdapter
  117. from requests.packages.urllib3.poolmanager import PoolManager
  118. import ssl
  119.  
  120. class SSLAdapter(HTTPAdapter):
  121. '''An HTTPS Transport Adapter that uses an arbitrary SSL version.'''
  122. def init_poolmanager(self, connections, maxsize, block=False):
  123. ssl_version = addon.getSetting("sslSetting")
  124. ssl_version = None if ssl_version == 'Auto' else ssl_version
  125. self.poolmanager = PoolManager(num_pools=connections,
  126. maxsize=maxsize,
  127. block=block,
  128. ssl_version=ssl_version)
  129.  
  130. urlMain = "http://www.netflix.com"
  131. session = None
  132. def newSession():
  133. s = requests.Session()
  134. s.mount('https://', SSLAdapter())
  135. s.headers.update({
  136. 'User-Agent': 'User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:21.0) Gecko/20130331 Firefox/21.0',
  137. })
  138. return s
  139. session = newSession()
  140. session.max_redirects = 5
  141. session.allow_redirects = True
  142.  
  143. def unescape(s):
  144. return htmlParser.unescape(s)
  145.  
  146. def load(url, post = None):
  147. debug("URL: " + url)
  148. r = ""
  149. user_agent = {'User-Agent': 'Mozilla/5.0'}
  150. try:
  151. if post:
  152. r = session.post(url, data=post, verify=verify_ssl).text
  153. else:
  154. r = session.get(url, verify=verify_ssl, headers=user_agent).text
  155. except AttributeError:
  156. xbmc.executebuiltin('XBMC.Notification(NetfliXBMC Error: Cookies have been deleted. Please try again.,10000,'+icon+')')
  157. newSession()
  158. saveState()
  159. if post:
  160. r = session.post(url, data=post, verify=verify_ssl).text
  161. else:
  162. r = session.get(url, verify=verify_ssl, headers=user_agent).text
  163. return r.encode('utf-8')
  164.  
  165. def saveState():
  166. tempfile = sessionFile+".tmp"
  167. if xbmcvfs.exists(tempfile):
  168. xbmcvfs.delete(tempfile)
  169. ser = pickle.dumps(session)
  170. fh = xbmcvfs.File(tempfile, 'wb')
  171. fh.write(ser)
  172. fh.close()
  173. if xbmcvfs.exists(sessionFile):
  174. xbmcvfs.delete(sessionFile)
  175. xbmcvfs.rename(tempfile, sessionFile)
  176.  
  177. # Load cached data
  178. if not os.path.isdir(addonUserDataFolder):
  179. os.mkdir(addonUserDataFolder)
  180. if not os.path.isdir(cacheFolder):
  181. os.mkdir(cacheFolder)
  182. if not os.path.isdir(cacheFolderCoversTMDB):
  183. os.mkdir(cacheFolderCoversTMDB)
  184. if not os.path.isdir(cacheFolderFanartTMDB):
  185. os.mkdir(cacheFolderFanartTMDB)
  186. if not os.path.isdir(libraryFolder):
  187. xbmcvfs.mkdir(libraryFolder)
  188. if not os.path.isdir(libraryFolderMovies):
  189. xbmcvfs.mkdir(libraryFolderMovies)
  190. if not os.path.isdir(libraryFolderTV):
  191. xbmcvfs.mkdir(libraryFolderTV)
  192. if os.path.exists(sessionFile):
  193. fh = xbmcvfs.File(sessionFile, 'rb')
  194. content = fh.read()
  195. fh.close()
  196. session = pickle.loads(content)
  197.  
  198. if not addon.getSetting("html5MessageShown"):
  199. dialog = xbmcgui.Dialog()
  200. ok = dialog.ok('IMPORTANT!', 'NetfliXBMC >=1.3.0 only supports the new Netflix HTML5 User Interface! The only browsers working with HTML5 DRM playback for now are Chrome>=37 (Win/OSX/Linux) and IExplorer>=11 (Win8.1 only). Make sure you have the latest version installed and check your Netflix settings. Using Silverlight may still partially work, but its not supported anymore. The HTML5 Player is also much faster, supports 1080p and gives you a smoother playback (especially on Linux). See forum.xbmc.org for more info...')
  201. addon.setSetting("html5MessageShown", "true")
  202.  
  203.  
  204. def index():
  205. if login():
  206. addDir(translation(30011), "", 'main', "", "movie")
  207. addDir(translation(30012), "", 'main', "", "tv")
  208. addDir(translation(30143), "", 'wiHome', "", "both")
  209. if not singleProfile:
  210. profileName = addon.getSetting("profileName")
  211. addDir(translation(30113) + ' - [COLOR blue]' + profileName + '[/COLOR]', "", 'profileDisplayUpdate', 'DefaultAddonService.png', type, contextEnable=False)
  212. xbmcplugin.endOfDirectory(pluginhandle)
  213.  
  214.  
  215. def profileDisplayUpdate():
  216. menuPath = xbmc.getInfoLabel('Container.FolderPath')
  217. if not showProfiles:
  218. addon.setSetting("profile", None)
  219. saveState()
  220. xbmc.executebuiltin('Container.Update('+menuPath+')')
  221.  
  222.  
  223. def main(type):
  224. #addDir(translation(30002), urlMain+"/MyList?leid=595&link=seeall", 'listVideos', "", type)
  225. addDir(translation(30002), urlMain+"/browse/my-list", 'listVideos', "", type)
  226. addDir(translation(30010), "", 'listViewingActivity', "", type)
  227. #addDir(translation(30003), urlMain+"/WiRecentAdditionsGallery?nRR=releaseDate&nRT=all&pn=1&np=1&actionMethod=json", 'listVideos', "", type)
  228. addDir(translation(30003), urlMain+"/browse/recently-added", 'listVideos', "", type)
  229. if type=="tv":
  230. #addDir(translation(30005), urlMain+"/WiGenre?agid=83", 'listVideos', "", type)
  231. addDir(translation(30005), urlMain+"/browse/genre/83", 'listVideos', "", type)
  232. addDir(translation(30007), "", 'listTvGenres', "", type)
  233. else:
  234. addDir(translation(30007), "WiGenre", 'listGenres', "", type)
  235. addDir(translation(30008), "", 'search', "", type)
  236. xbmcplugin.endOfDirectory(pluginhandle)
  237.  
  238.  
  239. def wiHome(type):
  240. content = load(urlMain+"/WiHome")
  241. match1 = re.compile('<div class="mrow(.+?)"><div class="hd clearfix"><h3> (.+?)</h3></div><div class="bd clearfix"><div class="slider triangleBtns " id="(.+?)"', re.DOTALL).findall(content)
  242. match2 = re.compile('class="hd clearfix"><h3><a href="(.+?)">(.+?)<', re.DOTALL).findall(content)
  243. for temp, title, sliderID in match1:
  244. if not "hide-completely" in temp:
  245. title = re.sub('<.(.+?)</.>', '', title)
  246. addDir(title.strip(), sliderID, 'listSliderVideos', "", type)
  247. for url, title in match2:
  248. if "WiAltGenre" in url or "WiSimilarsByViewType" in url or "WiRecentAdditionsGallery" in url:
  249. addDir(title.strip(), url, 'listVideos', "", type)
  250. xbmcplugin.endOfDirectory(pluginhandle)
  251.  
  252.  
  253. def listVideos(url, type, runAsWidget=False):
  254. if not runAsWidget:
  255. pDialog = xbmcgui.DialogProgress()
  256. pDialog.create('NetfliXBMC', translation(30142)+"...")
  257. pDialog.update( 0, translation(30142)+"...")
  258. xbmcplugin.setContent(pluginhandle, "movies")
  259. content = load(url)
  260. content = load(url) # Terrible... currently first call doesn't have the content, it requires two calls....
  261. if not 'id="page-LOGIN"' in content:
  262. if singleProfile and 'id="page-ProfilesGate"' in content:
  263. forceChooseProfile()
  264. else:
  265. if '<div id="queue"' in content:
  266. content = content[content.find('<div id="queue"'):]
  267. content = content.replace("\\t","").replace("\\n", "").replace("\\", "")
  268. match = None
  269. #if not match: match = re.compile('"boxarts":.*?"id":([0-9]+)', re.DOTALL).findall(content)
  270. if not match: match = re.compile('"\$type":"leaf",.*?"id":([0-9]+)', re.DOTALL).findall(content)
  271. if not match: match = re.compile('<a href="\/watch\/([0-9]+)', re.DOTALL).findall(content)
  272. if not match: match = re.compile('<span id="dbs(.+?)_.+?alt=".+?"', re.DOTALL).findall(content)
  273. if not match: match = re.compile('<span class="title.*?"><a id="b(.+?)_', re.DOTALL).findall(content)
  274. #if not match: match = re.compile('<a href="http://dvd.netflix.com/WiPlayer\?movieid=(.+?)&', re.DOTALL).findall(content)
  275. #if not match: match = re.compile('<a class="playHover" href=".+?WiPlayer\?movieid=(.+?)&', re.DOTALL).findall(content)
  276. if not match: match = re.compile('"boxart":".+?","titleId":(.+?),', re.DOTALL).findall(content)
  277. if not match: match = re.compile('WiPlayer\?movieid=([0-9]+?)&', re.DOTALL).findall(content)
  278. i = 1
  279. #ok = xbmc.log(content)
  280. #ok = xbmcgui.Dialog().ok('Match',match[0])
  281. for videoID in match:
  282. if int(videoID)>10000000:
  283. if not runAsWidget:
  284. pDialog.update(i*100/len(match), translation(30142)+"...")
  285. listVideo(videoID, "", "", False, False, type)
  286. i+=1
  287. match1 = re.compile('&pn=(.+?)&', re.DOTALL).findall(url)
  288. match2 = re.compile('&from=(.+?)&', re.DOTALL).findall(url)
  289. matchApiRoot = re.compile('"API_ROOT":"(.+?)"', re.DOTALL).findall(content)
  290. matchApiBase = re.compile('"API_BASE_URL":"(.+?)"', re.DOTALL).findall(content)
  291. matchIdentifier = re.compile('"BUILD_IDENTIFIER":"(.+?)"', re.DOTALL).findall(content)
  292. if "agid=" in url and matchApiRoot and matchApiBase and matchIdentifier:
  293. genreID = url[url.find("agid=")+5:]
  294. addDir(translation(30001), matchApiRoot[0]+matchApiBase[0]+"/"+matchIdentifier[0]+"/wigenre?genreId="+genreID+"&full=false&from=51&to=100&_retry=0", 'listVideos', "", type)
  295. elif match1:
  296. currentPage = match1[0]
  297. nextPage = str(int(currentPage)+1)
  298. addDir(translation(30001), url.replace("&pn="+currentPage+"&", "&pn="+nextPage+"&"), 'listVideos', "", type)
  299. elif match2:
  300. currentFrom = match2[0]
  301. nextFrom = str(int(currentFrom)+50)
  302. currentTo = str(int(currentFrom)+49)
  303. nextTo = str(int(currentFrom)+99)
  304. addDir(translation(30001), url.replace("&from="+currentFrom+"&", "&from="+nextFrom+"&").replace("&to="+currentTo+"&", "&to="+nextTo+"&"), 'listVideos', "", type)
  305. if forceView and not runAsWidget:
  306. xbmc.executebuiltin('Container.SetViewMode('+viewIdVideos+')')
  307. xbmcplugin.endOfDirectory(pluginhandle)
  308. else:
  309. deleteCookies()
  310. xbmc.executebuiltin('XBMC.Notification(NetfliXBMC:,'+str(translation(30127))+',15000,'+icon+')')
  311.  
  312.  
  313. def listSliderVideos(sliderID, type, runAsWidget=False):
  314. if not runAsWidget:
  315. pDialog = xbmcgui.DialogProgress()
  316. pDialog.create('NetfliXBMC', translation(30142)+"...")
  317. pDialog.update( 0, translation(30142)+"...")
  318. xbmcplugin.setContent(pluginhandle, "movies")
  319. content = load(urlMain+"/WiHome")
  320. if not 'id="page-LOGIN"' in content:
  321. if singleProfile and 'id="page-ProfilesGate"' in content:
  322. forceChooseProfile()
  323. else:
  324. content = content.replace("\\t","").replace("\\n", "").replace("\\", "")
  325. contentMain = content
  326. content = content[content.find('id="'+sliderID+'"'):]
  327. content = content[:content.find('class="ft"')]
  328. match = re.compile('<span id="dbs(.+?)_', re.DOTALL).findall(content)
  329. i = 1
  330. for videoID in match:
  331. listVideo(videoID, "", "", False, False, type)
  332. i+=1
  333. spl = contentMain.split('"remainderHTML":')
  334. for i in range(1, len(spl), 1):
  335. entry = spl[i]
  336. entry = entry[:entry.find('"rowId":')]
  337. if '"domId":"'+sliderID+'"' in entry:
  338. match = re.compile('<span id="dbs(.+?)_', re.DOTALL).findall(entry)
  339. i = 1
  340. for videoID in match:
  341. if not runAsWidget:
  342. pDialog.update(i*100/(len(match)+10), translation(30142)+"...")
  343. listVideo(videoID, "", "", False, False, type)
  344. i+=1
  345. if forceView and not runAsWidget:
  346. xbmc.executebuiltin('Container.SetViewMode('+viewIdVideos+')')
  347. xbmcplugin.endOfDirectory(pluginhandle)
  348. else:
  349. deleteCookies()
  350. xbmc.executebuiltin('XBMC.Notification(NetfliXBMC:,'+str(translation(30127))+',15000,'+icon+')')
  351.  
  352.  
  353. def listSearchVideos(url, type, runAsWidget=False):
  354. if not runAsWidget:
  355. pDialog = xbmcgui.DialogProgress()
  356. pDialog.create('NetfliXBMC', translation(30142)+"...")
  357. pDialog.update( 0, translation(30142)+"...")
  358. xbmcplugin.setContent(pluginhandle, "movies")
  359. content = load(url)
  360. content = json.loads(content)
  361. i = 1
  362. if "galleryVideos" in content:
  363. for item in content["galleryVideos"]["items"]:
  364. if not runAsWidget:
  365. pDialog.update(i*100/len(content["galleryVideos"]["items"]), translation(30142)+"...")
  366. listVideo(str(item["id"]), "", "", False, False, type)
  367. i+=1
  368. if forceView and not runAsWidget:
  369. xbmc.executebuiltin('Container.SetViewMode('+viewIdVideos+')')
  370. xbmcplugin.endOfDirectory(pluginhandle)
  371. else:
  372. xbmc.executebuiltin('XBMC.Notification(NetfliXBMC:,'+str(translation(30146))+',5000,'+icon+')')
  373.  
  374. def clean_filename(n, chars=None):
  375. if isinstance(n, str):
  376. return (''.join(c for c in unicode(n, "utf-8") if c not in '/\\:?"*|<>')).strip(chars)
  377. elif isinstance(n, unicode):
  378. return (''.join(c for c in n if c not in '/\\:?"*|<>')).strip(chars)
  379.  
  380. def listVideo(videoID, title, thumbUrl, tvshowIsEpisode, hideMovies, type):
  381. videoDetails = getVideoInfo(videoID)
  382. match = re.compile('<span class="title.*?>(.+?)<', re.DOTALL).findall(videoDetails)
  383. if not title:
  384. title = match[0].strip()
  385. year = ""
  386. match = re.compile('<span class="year.*?>(.+?)<', re.DOTALL).findall(videoDetails)
  387. if match:
  388. year = match[0]
  389. if not thumbUrl:
  390. match = re.compile('src="(.+?)"', re.DOTALL).findall(videoDetails)
  391. thumbUrl = match[0].replace("/webp/","/images/").replace(".webp",".jpg")
  392. match = re.compile('<span class="mpaaRating.*?>(.+?)<', re.DOTALL).findall(videoDetails)
  393. mpaa = ""
  394. if match:
  395. mpaa = match[0].strip()
  396. match = re.compile('<span class="duration.*?>(.+?)<', re.DOTALL).findall(videoDetails)
  397. duration = ""
  398. if match:
  399. duration = match[0].lower()
  400. if duration.split(' ')[-1] in ["minutes", "minutos", "minuter", "minutter", "minuuttia", "minuten"]:
  401. videoType = "movie"
  402. videoTypeTemp = videoType
  403. duration = duration.split(" ")[0]
  404. else:
  405. videoTypeTemp = "tv"
  406. if tvshowIsEpisode:
  407. videoType = "episode"
  408. year = ""
  409. else:
  410. videoType = "tvshow"
  411. duration = ""
  412. if useTMDb:
  413. yearTemp = year
  414. titleTemp = title
  415. if " - " in titleTemp:
  416. titleTemp = titleTemp[titleTemp.find(" - ")+3:]
  417. if "-" in yearTemp:
  418. yearTemp = yearTemp.split("-")[0]
  419. filename = clean_filename(videoID)+".jpg"
  420. filenameNone = clean_filename(videoID)+".none"
  421. coverFile = os.path.join(cacheFolderCoversTMDB, filename)
  422. coverFileNone = os.path.join(cacheFolderCoversTMDB, filenameNone)
  423. if not os.path.exists(coverFile) and not os.path.exists(coverFileNone):
  424. debug("Downloading Cover art. videoType:"+videoTypeTemp+", videoID:" + videoID + ", title:"+titleTemp+", year:"+yearTemp)
  425. xbmc.executebuiltin('XBMC.RunScript('+downloadScript+', '+urllib.quote_plus(videoTypeTemp)+', '+urllib.quote_plus(videoID)+', '+urllib.quote_plus(titleTemp)+', '+urllib.quote_plus(yearTemp)+')')
  426. match = re.compile('src=".+?">.*?<.*?>(.+?)<', re.DOTALL).findall(videoDetails)
  427. desc = ""
  428. if match:
  429. descTemp = match[0].decode("utf-8", 'ignore')
  430. #replace all embedded unicode in unicode (Norwegian problem)
  431. descTemp = descTemp.replace('u2013', u'\u2013').replace('u2026', u'\u2026')
  432. desc = htmlParser.unescape(descTemp)
  433. match = re.compile('Director:</dt><dd>(.+?)<', re.DOTALL).findall(videoDetails)
  434. director = ""
  435. if match:
  436. director = match[0].strip()
  437. match = re.compile('<span class="genre.*?>(.+?)<', re.DOTALL).findall(videoDetails)
  438. genre = ""
  439. if match:
  440. genre = match[0]
  441. match = re.compile('<span class="rating">(.+?)<', re.DOTALL).findall(videoDetails)
  442. rating = ""
  443. if match:
  444. rating = match[0]
  445. title = htmlParser.unescape(title.decode("utf-8"))
  446. nextMode = "playVideoMain"
  447. if browseTvShows and videoType == "tvshow":
  448. nextMode = "listSeasons"
  449. added = False
  450. if "/MyList" in url and videoTypeTemp==type:
  451. addVideoDirR(title, videoID, nextMode, thumbUrl, videoType, desc, duration, year, mpaa, director, genre, rating)
  452. added = True
  453. elif videoType == "movie" and hideMovies:
  454. pass
  455. elif videoTypeTemp==type or type=="both":
  456. addVideoDir(title, videoID, nextMode, thumbUrl, videoType, desc, duration, year, mpaa, director, genre, rating)
  457. added = True
  458. return added
  459.  
  460.  
  461. def listGenres(type, videoType):
  462. xbmcplugin.addSortMethod(pluginhandle, xbmcplugin.SORT_METHOD_LABEL)
  463. if isKidsProfile:
  464. type = 'KidsAltGenre'
  465. content = load(urlMain+"/WiHome")
  466. match = re.compile('/'+type+'\\?agid=(.+?)">(.+?)<', re.DOTALL).findall(content)
  467. # A number of categories (especially in the Kids genres) have duplicate entires and a lot of whitespice; create a stripped unique set
  468. unique_match = set((k[0].strip(), k[1].strip()) for k in match)
  469. for genreID, title in unique_match:
  470. if not genreID=="83":
  471. if isKidsProfile:
  472. addDir(title, urlMain+"/"+type+"?agid="+genreID+"&pn=1&np=1&actionMethod=json", 'listVideos', "", videoType)
  473. else:
  474. addDir(title, urlMain+"/"+type+"?agid="+genreID, 'listVideos', "", videoType)
  475. xbmcplugin.endOfDirectory(pluginhandle)
  476.  
  477.  
  478. def listTvGenres(videoType):
  479. xbmcplugin.addSortMethod(pluginhandle, xbmcplugin.SORT_METHOD_LABEL)
  480. content = load(urlMain+"/WiGenre?agid=83")
  481. content = content[content.find('id="subGenres_menu"'):]
  482. content = content[:content.find('</div>')]
  483. match = re.compile('<li ><a href=".+?/WiGenre\\?agid=(.+?)&.+?"><span>(.+?)<', re.DOTALL).findall(content)
  484. for genreID, title in match:
  485. addDir(title, urlMain+"/WiGenre?agid="+genreID, 'listVideos', "", videoType)
  486. xbmcplugin.endOfDirectory(pluginhandle)
  487.  
  488.  
  489. def listSeasons(seriesName, seriesID, thumb):
  490. playVideoEpisodes(seriesID)
  491. return
  492.  
  493. content = getSeriesInfo(seriesID)
  494. content = json.loads(content)
  495. seasons = []
  496. for item in content["episodes"]:
  497. if item[0]["season"] not in seasons:
  498. seasons.append(item[0]["season"])
  499. for season in seasons:
  500. addSeasonDir("Season "+str(season), str(season), 'listEpisodes', thumb, seriesName, seriesID)
  501. xbmcplugin.endOfDirectory(pluginhandle)
  502.  
  503.  
  504. def listEpisodes(seriesID, season):
  505. xbmcplugin.setContent(pluginhandle, "episodes")
  506. content = getSeriesInfo(seriesID)
  507. content = json.loads(content)
  508. for test in content["episodes"]:
  509. for item in test:
  510. episodeSeason = str(item["season"])
  511. if episodeSeason == season:
  512. episodeID = str(item["episodeId"])
  513. episodeNr = str(item["episode"])
  514. episodeTitle = (episodeNr + ". " + item["title"]).encode('utf-8')
  515. duration = item["runtime"]
  516. bookmarkPosition = item["bookmarkPosition"]
  517. playcount=0
  518. if (duration>0 and float(bookmarkPosition)/float(duration))>=0.9:
  519. playcount=1
  520. desc = item["synopsis"].encode('utf-8')
  521. try:
  522. thumb = item["stills"][0]["url"]
  523. except:
  524. thumb = ""
  525. addEpisodeDir(episodeTitle, episodeID, 'playVideoMain', thumb, desc, str(duration), season, episodeNr, seriesID, playcount)
  526. if forceView:
  527. xbmc.executebuiltin('Container.SetViewMode('+viewIdEpisodes+')')
  528. xbmcplugin.endOfDirectory(pluginhandle)
  529.  
  530.  
  531. def listViewingActivity(type, runAsWidget=False):
  532. if not runAsWidget:
  533. pDialog = xbmcgui.DialogProgress()
  534. pDialog.create('NetfliXBMC', translation(30142)+"...")
  535. pDialog.update( 0, translation(30142)+"...")
  536. xbmcplugin.setContent(pluginhandle, "movies")
  537. content = load(urlMain+"/WiViewingActivity")
  538. count = 0
  539. videoIDs = []
  540. spl = re.compile('(<li .*?data-series=.*?</li>)', re.DOTALL).findall(content)
  541. #spl = content.split('')
  542. for i in range(1, len(spl), 1):
  543. entry = spl[i]
  544. if not runAsWidget:
  545. pDialog.update((count+1)*100/len(spl), translation(30142)+"...")
  546. matchId = re.compile('data-movieid="(.*?)"', re.DOTALL).findall(entry)
  547. if matchId:
  548. videoID = matchId[0]
  549. match = re.compile('class="col date nowrap">(.+?)<', re.DOTALL).findall(entry)
  550. date = match[0]
  551. matchTitle1 = re.compile('class="seriestitle">(.+?)</a>', re.DOTALL).findall(entry)
  552. matchTitle2 = re.compile('class="col title">.+?>(.+?)<', re.DOTALL).findall(entry)
  553. if matchTitle1:
  554. title = htmlParser.unescape(matchTitle1[0].decode("utf-8")).replace("</span>", "").encode("utf-8")
  555. elif matchTitle2:
  556. title = matchTitle2[0]
  557. else:
  558. title = ""
  559. title = date+" - "+title
  560. if videoID not in videoIDs:
  561. videoIDs.append(videoID)
  562. # due to limitations in the netflix api, there is no way to get the seriesId of an
  563. # episode, so the 4 param is set to True to treat tv episodes the same as movies.
  564. added = listVideo(videoID, title, "", True, False, type)
  565. if added:
  566. count += 1
  567. if count == 40:
  568. break
  569. if forceView and not runAsWidget:
  570. xbmc.executebuiltin('Container.SetViewMode('+viewIdActivity+')')
  571. xbmcplugin.endOfDirectory(pluginhandle)
  572.  
  573.  
  574. def getVideoInfo(videoID):
  575. cacheFile = os.path.join(cacheFolder, videoID+".cache")
  576. content = ""
  577. if os.path.exists(cacheFile):
  578. fh = xbmcvfs.File(cacheFile, 'r')
  579. content = fh.read()
  580. fh.close()
  581. if not content:
  582. content = load(urlMain+"/JSON/BOB?movieid="+videoID)
  583. fh = xbmcvfs.File(cacheFile, 'w')
  584. fh.write(content)
  585. fh.close()
  586. return content.replace("\\t","").replace("\\n", "").replace("\\", "")
  587.  
  588.  
  589. def getSeriesInfo(seriesID):
  590. cacheFile = os.path.join(cacheFolder, seriesID+"_episodes.cache")
  591. content = ""
  592. if os.path.exists(cacheFile) and (time.time()-os.path.getmtime(cacheFile) < 60*5):
  593. fh = xbmcvfs.File(cacheFile, 'r')
  594. content = fh.read()
  595. fh.close()
  596. if not content:
  597. url = "http://api-global.netflix.com/desktop/odp/episodes?languages="+language+"&forceEpisodes=true&routing=redirect&video="+seriesID+"&country="+country
  598. content = load(url)
  599. fh = xbmcvfs.File(cacheFile, 'w')
  600. fh.write(content)
  601. fh.close()
  602.  
  603. # if netflix throws exception they may still return content after the exception
  604. index = content.find('{"title":')
  605. if index != -1:
  606. content = content[index:]
  607.  
  608. return content
  609.  
  610.  
  611. def addMyListToLibrary():
  612. if not singleProfile:
  613. token = ""
  614. if addon.getSetting("profile"):
  615. token = addon.getSetting("profile")
  616. load("https://www.netflix.com/SwitchProfile?tkn="+token)
  617.  
  618. content = load(urlMain+"/MyList?leid=595&link=seeall")
  619. if not 'id="page-LOGIN"' in content:
  620. if singleProfile and 'id="page-ProfilesGate"' in content:
  621. forceChooseProfile()
  622. else:
  623. if '<div id="queue"' in content:
  624. content = content[content.find('<div id="queue"'):]
  625. content = content.replace("\\t","").replace("\\n", "").replace("\\", "")
  626. match1 = re.compile('<span id="dbs(.+?)_.+?alt=".+?"', re.DOTALL).findall(content)
  627. match2 = re.compile('<span class="title.*?"><a id="b(.+?)_', re.DOTALL).findall(content)
  628. match3 = re.compile('<a href="http://dvd.netflix.com/WiPlayer\?movieid=(.+?)&', re.DOTALL).findall(content)
  629. match4 = re.compile('<a class="playHover" href=".+?WiPlayer\?movieid=(.+?)&', re.DOTALL).findall(content)
  630. match5 = re.compile('"boxart":".+?","titleId":(.+?),', re.DOTALL).findall(content)
  631. if match1:
  632. match = match1
  633. elif match2:
  634. match = match2
  635. elif match3:
  636. match = match3
  637. elif match4:
  638. match = match4
  639. elif match5:
  640. match = match5
  641.  
  642.  
  643.  
  644. for videoID in match:
  645. videoDetails = getVideoInfo(videoID)
  646. match = re.compile('<span class="title ".*?>(.+?)<\/span>', re.DOTALL).findall(videoDetails)
  647. title = match[0].strip()
  648. title = htmlParser.unescape(title.decode("utf-8"))
  649. match = re.compile('<span class="year".*?>(.+?)<\/span>', re.DOTALL).findall(videoDetails)
  650. year = ""
  651. if match:
  652. year = match[0]
  653. match = re.compile('<span class="duration.*?".*?>(.+?)<\/span>', re.DOTALL).findall(videoDetails)
  654. duration = ""
  655. if match:
  656. duration = match[0].lower()
  657. if "minutes" in duration:
  658. try:
  659. if year:
  660. title = title+" ("+year+")"
  661. addMovieToLibrary(videoID, title, False)
  662. except:
  663. pass
  664. else:
  665. try:
  666. addSeriesToLibrary(videoID, title, "", False)
  667. except:
  668. pass
  669. if updateDB:
  670. xbmc.executebuiltin('UpdateLibrary(video)')
  671.  
  672. def playVideo(id):
  673. listitem = xbmcgui.ListItem(path=fakeVidPath)
  674. xbmcplugin.setResolvedUrl(pluginhandle, True, listitem)
  675. playVideoMain(id)
  676. xbmc.PlayList(xbmc.PLAYLIST_VIDEO).clear()
  677.  
  678.  
  679. def playVideoMain(id):
  680. xbmc.Player().stop()
  681. if singleProfile:
  682. #url = urlMain+"/WiPlayer?movieid="+id
  683. url = urlMain+"/watch/"+id
  684. else:
  685. token = ""
  686. if addon.getSetting("profile"):
  687. token = addon.getSetting("profile")
  688. url = "https://www.netflix.com/SwitchProfile?tkn="+token+"&nextpage="+urllib.quote_plus(urlMain+"/WiPlayer?movieid="+id)
  689. if osOSX:
  690. launchChrome(url)
  691. #xbmc.executebuiltin("RunPlugin(plugin://plugin.program.chrome.launcher/?url="+urllib.quote_plus(url)+"&mode=showSite&kiosk="+kiosk+")")
  692. try:
  693. xbmc.sleep(5000)
  694. subprocess.Popen('cliclick c:500,500', shell=True)
  695. subprocess.Popen('cliclick kp:arrow-up', shell=True)
  696. xbmc.sleep(5000)
  697. subprocess.Popen('cliclick c:500,500', shell=True)
  698. subprocess.Popen('cliclick kp:arrow-up', shell=True)
  699. xbmc.sleep(5000)
  700. subprocess.Popen('cliclick c:500,500', shell=True)
  701. subprocess.Popen('cliclick kp:arrow-up', shell=True)
  702. except:
  703. pass
  704. elif osAndroid:
  705. xbmc.executebuiltin('XBMC.StartAndroidActivity("","android.intent.action.VIEW","","' + urlMain+'/watch/' + id + '")')
  706. elif osLinux:
  707. if linuxUseShellScript:
  708. xbmc.executebuiltin('LIRC.Stop')
  709.  
  710. call = '"'+browserScript+'" "'+url+'"';
  711. debug("Browser Call: " + call)
  712. subprocess.call(call, shell=True)
  713.  
  714. xbmc.executebuiltin('LIRC.Start')
  715. else:
  716. launchChrome(url)
  717. #xbmc.executebuiltin("RunPlugin(plugin://plugin.program.chrome.launcher/?url="+urllib.quote_plus(url)+"&mode=showSite&kiosk="+kiosk+")")
  718. try:
  719. xbmc.sleep(5000)
  720. subprocess.Popen('xdotool mousemove 9999 9999', shell=True)
  721. xbmc.sleep(5000)
  722. subprocess.Popen('xdotool mousemove 9999 9999', shell=True)
  723. xbmc.sleep(5000)
  724. subprocess.Popen('xdotool mousemove 9999 9999', shell=True)
  725. except:
  726. pass
  727. elif osWin:
  728. if winBrowser == 1:
  729. path = 'C:\\Program Files\\Internet Explorer\\iexplore.exe'
  730. path64 = 'C:\\Program Files (x86)\\Internet Explorer\\iexplore.exe'
  731. if os.path.exists(path):
  732. subprocess.Popen('"'+path+'" -k "'+url+'"', shell=False)
  733. elif os.path.exists(path64):
  734. subprocess.Popen('"'+path64+'" -k "'+url+'"', shell=False)
  735. else:
  736. launchChrome(url)
  737. #xbmc.executebuiltin("RunPlugin(plugin://plugin.program.chrome.launcher/?url="+urllib.quote_plus(url)+"&mode=showSite&kiosk="+kiosk+")")
  738. if useUtility:
  739. subprocess.Popen('"'+utilityPath+'"', shell=False)
  740.  
  741. myWindow = window('window.xml', addon.getAddonInfo('path'), 'default',)
  742. myWindow.doModal()
  743. myWindow.stopWakeupThread() # insurance, in case self.close() wasn't the method by which the window was closed
  744.  
  745. def playVideoEpisodes(id):
  746. xbmc.Player().stop()
  747. if singleProfile:
  748. #url = urlMain+"/WiPlayer?movieid="+id
  749. url = urlMain+"/title/"+id
  750. else:
  751. token = ""
  752. if addon.getSetting("profile"):
  753. token = addon.getSetting("profile")
  754. url = "https://www.netflix.com/SwitchProfile?tkn="+token+"&nextpage="+urllib.quote_plus(urlMain+"/WiPlayer?movieid="+id)
  755. if osOSX:
  756. launchChrome(url)
  757. #xbmc.executebuiltin("RunPlugin(plugin://plugin.program.chrome.launcher/?url="+urllib.quote_plus(url)+"&mode=showSite&kiosk="+kiosk+")")
  758. try:
  759. xbmc.sleep(5000)
  760. subprocess.Popen('cliclick c:500,500', shell=True)
  761. subprocess.Popen('cliclick kp:arrow-up', shell=True)
  762. xbmc.sleep(5000)
  763. subprocess.Popen('cliclick c:500,500', shell=True)
  764. subprocess.Popen('cliclick kp:arrow-up', shell=True)
  765. xbmc.sleep(5000)
  766. subprocess.Popen('cliclick c:500,500', shell=True)
  767. subprocess.Popen('cliclick kp:arrow-up', shell=True)
  768. except:
  769. pass
  770. elif osAndroid:
  771. xbmc.executebuiltin('XBMC.StartAndroidActivity("","android.intent.action.VIEW","","' + urlMain+'/watch/' + id + '")')
  772. elif osLinux:
  773. if linuxUseShellScript:
  774. xbmc.executebuiltin('LIRC.Stop')
  775.  
  776. call = '"'+browserScript+'" "'+url+'"';
  777. debug("Browser Call: " + call)
  778. subprocess.call(call, shell=True)
  779.  
  780. xbmc.executebuiltin('LIRC.Start')
  781. else:
  782. launchChrome(url)
  783. #xbmc.executebuiltin("RunPlugin(plugin://plugin.program.chrome.launcher/?url="+urllib.quote_plus(url)+"&mode=showSite&kiosk="+kiosk+")")
  784. try:
  785. xbmc.sleep(5000)
  786. subprocess.Popen('xdotool mousemove 9999 9999', shell=True)
  787. xbmc.sleep(5000)
  788. subprocess.Popen('xdotool mousemove 9999 9999', shell=True)
  789. xbmc.sleep(5000)
  790. subprocess.Popen('xdotool mousemove 9999 9999', shell=True)
  791. except:
  792. pass
  793. elif osWin:
  794. if winBrowser == 1:
  795. path = 'C:\\Program Files\\Internet Explorer\\iexplore.exe'
  796. path64 = 'C:\\Program Files (x86)\\Internet Explorer\\iexplore.exe'
  797. if os.path.exists(path):
  798. subprocess.Popen('"'+path+'" -k "'+url+'"', shell=False)
  799. elif os.path.exists(path64):
  800. subprocess.Popen('"'+path64+'" -k "'+url+'"', shell=False)
  801. else:
  802. launchChrome(url)
  803. #xbmc.executebuiltin("RunPlugin(plugin://plugin.program.chrome.launcher/?url="+urllib.quote_plus(url)+"&mode=showSite&kiosk="+kiosk+")")
  804. if useUtility:
  805. subprocess.Popen('"'+utilityPath+'"', shell=False)
  806.  
  807. myWindow = window('window.xml', addon.getAddonInfo('path'), 'default',)
  808. myWindow.doModal()
  809. myWindow.stopWakeupThread() # insurance, in case self.close() wasn't the method by which the window was closed
  810.  
  811. def launchChrome(url):
  812. kiosk = "yes"
  813. if dontUseKiosk:
  814. kiosk = "no"
  815.  
  816. profileFolder = ""
  817. if useChromeProfile:
  818. if not os.path.exists(chromeUserDataFolder):
  819. import zipfile
  820. zip = os.path.join(addonDir, "resources", "chrome-user-data.zip")
  821. with open(zip, "rb") as zf:
  822. z = zipfile.ZipFile(zf)
  823. z.extractall(addonUserDataFolder)
  824. profileFolder = "&profileFolder="+urllib.quote_plus(chromeUserDataFolder)
  825.  
  826. # Inject cookies
  827. chrome_cookies.inject_cookies_into_chrome(session, os.path.join(chromeUserDataFolder, "Default", "Cookies"))
  828.  
  829.  
  830. xbmc.executebuiltin("RunPlugin(plugin://plugin.program.chrome.launcher/?url="+urllib.quote_plus(url)+"&mode=showSite&kiosk="+kiosk+profileFolder+")")
  831.  
  832. def configureUtility():
  833. if osWin:
  834. subprocess.Popen('"'+utilityPath+'"'+' config=yes', shell=False)
  835.  
  836. def chromePluginOptions():
  837. url = "chrome-extension://najegmllpphoobggcngjhcpknknljhkj/html/options.html"
  838. launchChrome(url)
  839.  
  840. def deleteCookies():
  841. if os.path.exists(cookieFile):
  842. os.remove(cookieFile)
  843. xbmc.executebuiltin('XBMC.Notification(NetfliXBMC:,Cookies have been deleted!,5000,'+icon+')')
  844. if os.path.exists(sessionFile):
  845. os.remove(sessionFile)
  846. xbmc.executebuiltin('XBMC.Notification(NetfliXBMC:,Session cookies have been deleted!,5000,'+icon+')')
  847.  
  848.  
  849. def deleteCache():
  850. if os.path.exists(cacheFolder):
  851. try:
  852. shutil.rmtree(cacheFolder)
  853. xbmc.executebuiltin('XBMC.Notification(NetfliXBMC:,Cache has been deleted!,5000,'+icon+')')
  854. except:
  855. pass
  856.  
  857. def deleteChromeUserDataFolder():
  858. if os.path.exists(chromeUserDataFolder):
  859. try:
  860. shutil.rmtree(chromeUserDataFolder)
  861. xbmc.executebuiltin('XBMC.Notification(NetfliXBMC:,Chrome UserData has been deleted!,5000,'+icon+')')
  862. except:
  863. pass
  864.  
  865. def resetAddon():
  866. dialog = xbmcgui.Dialog()
  867. if dialog.yesno("NetfliXBMC:", "Really reset the addon?"):
  868. if os.path.exists(addonUserDataFolder):
  869. try:
  870. shutil.rmtree(addonUserDataFolder)
  871. xbmc.executebuiltin('XBMC.Notification(NetfliXBMC:,Addon has been reset!,5000,'+icon+')')
  872. except:
  873. pass
  874.  
  875. def search(type):
  876. keyboard = xbmc.Keyboard('', translation(30008))
  877. keyboard.doModal()
  878. if keyboard.isConfirmed() and keyboard.getText():
  879. search_string = keyboard.getText().replace(" ", "+")
  880. listSearchVideos("http://api-global.netflix.com/desktop/search/instantsearch?esn=www&term="+search_string+"&locale="+language+"&country="+country+"&authURL="+auth+"&_retry=0&routing=redirect", type)
  881.  
  882. def addToQueue(id):
  883. if authMyList:
  884. encodedAuth = urllib.urlencode({'authURL': authMyList})
  885. load(urlMain+"/AddToQueue?movieid="+id+"&qtype=INSTANT&"+encodedAuth)
  886. xbmc.executebuiltin('XBMC.Notification(NetfliXBMC:,'+str(translation(30144))+',3000,'+icon+')')
  887. else:
  888. debug("Attempted to addToQueue without valid authMyList")
  889.  
  890. def removeFromQueue(id):
  891. if authMyList:
  892. encodedAuth = urllib.urlencode({'authURL': authMyList})
  893. load(urlMain+"/QueueDelete?"+encodedAuth+"&qtype=ED&movieid="+id)
  894. xbmc.executebuiltin('XBMC.Notification(NetfliXBMC:,'+str(translation(30145))+',3000,'+icon+')')
  895. xbmc.executebuiltin("Container.Refresh")
  896. else:
  897. debug("Attempted to removeFromQueue without valid authMyList")
  898.  
  899.  
  900. def displayLoginProgress(progressWindow, value, message):
  901. progressWindow.update( value, "", message, "" )
  902. if progressWindow.iscanceled():
  903. return False
  904. else:
  905. return True
  906.  
  907.  
  908. def login():
  909. #setup login progress display
  910. loginProgress = xbmcgui.DialogProgress()
  911. loginProgress.create('NETFLIXBMC', str(translation(30216)) + '...')
  912. displayLoginProgress(loginProgress, 25, str(translation(30217)))
  913.  
  914. session.cookies.clear()
  915. content = load(urlMain+"/Login")
  916. match = re.compile('"LOCALE":"(.+?)"', re.DOTALL|re.IGNORECASE).findall(content)
  917. if match and not addon.getSetting("language"):
  918. addon.setSetting("language", match[0])
  919. if not "Sorry, Netflix is not available in your country yet." in content and not "Sorry, Netflix hasn't come to this part of the world yet" in content:
  920. match = re.compile('id="signout".+?authURL=(.+?)"', re.DOTALL).findall(content)
  921. if match:
  922. addon.setSetting("auth", match[0])
  923. if 'id="page-LOGIN"' in content:
  924. match = re.compile('name="authURL" value="(.+?)"', re.DOTALL).findall(content)
  925. authUrl = match[0]
  926. addon.setSetting("auth", authUrl)
  927. #postdata = "authURL="+urllib.quote_plus(authUrl)+"&email="+urllib.quote_plus(username)+"&password="+urllib.quote_plus(password)+"&RememberMe=on"
  928. postdata ={ "authURL":authUrl,
  929. "email":username,
  930. "password":password,
  931. "RememberMe":"on"
  932. }
  933. #content = load("https://signup.netflix.com/Login", "authURL="+urllib.quote_plus(authUrl)+"&email="+urllib.quote_plus(username)+"&password="+urllib.quote_plus(password)+"&RememberMe=on")
  934. displayLoginProgress(loginProgress, 50, str(translation(30218)))
  935. content = load("https://signup.netflix.com/Login", postdata)
  936. if 'id="page-LOGIN"' in content:
  937. # Login Failed
  938. xbmc.executebuiltin('XBMC.Notification(NetfliXBMC:,'+str(translation(30127))+',15000,'+icon+')')
  939. return False
  940. match = re.compile('"LOCALE":"(.+?)"', re.DOTALL|re.IGNORECASE).findall(content)
  941. if match and not addon.getSetting("language"):
  942. addon.setSetting("language", match[0])
  943. match = re.compile('"COUNTRY":"(.+?)"', re.DOTALL|re.IGNORECASE).findall(content)
  944. if match:
  945. # always overwrite the country code, to cater for switching regions
  946. debug("Setting Country: " + match[0])
  947. addon.setSetting("country", match[0])
  948. saveState()
  949. displayLoginProgress(loginProgress, 75, str(translation(30219)))
  950.  
  951. if not addon.getSetting("profile") and not singleProfile:
  952. chooseProfile()
  953. elif not singleProfile and showProfiles:
  954. chooseProfile()
  955. elif not singleProfile and not showProfiles:
  956. loadProfile()
  957. else:
  958. getMyListChangeAuthorisation()
  959. if loginProgress:
  960. if not displayLoginProgress(loginProgress, 100, str(translation(30220))):
  961. return False
  962. xbmc.sleep(500)
  963. loginProgress.close()
  964. return True
  965. else:
  966. xbmc.executebuiltin('XBMC.Notification(NetfliXBMC:,'+str(translation(30126))+',10000,'+icon+')')
  967. if loginProgress:
  968. loginProgress.close()
  969. return False
  970.  
  971. def debug(message):
  972. if debug:
  973. print message
  974.  
  975. def loadProfile():
  976. savedProfile = addon.getSetting("profile")
  977. if savedProfile:
  978. load("https://api-global.netflix.com/desktop/account/profiles/switch?switchProfileGuid="+savedProfile)
  979. saveState()
  980. else:
  981. debug("LoadProfile: No stored profile found")
  982. getMyListChangeAuthorisation()
  983.  
  984. def chooseProfile():
  985. content = load("https://www.netflix.com/ProfilesGate?nextpage=http%3A%2F%2Fwww.netflix.com%2FDefault")
  986. matchType = 0
  987. match = re.compile('"profileName":"(.+?)".+?token":"(.+?)"', re.DOTALL).findall(content)
  988. if len(match):
  989. matchType = 1
  990. if not len(match):
  991. match = re.compile('"firstName":"(.+?)".+?guid":"(.+?)".+?experience":"(.+?)"', re.DOTALL).findall(content)
  992. if len(match):
  993. matchType = 1
  994. if not len(match):
  995. match = re.compile('"experience":"(.+?)".+?guid":"(.+?)".+?profileName":"(.+?)"', re.DOTALL).findall(content)
  996. if len(match):
  997. matchType = 2
  998. profiles = []
  999. # remove any duplicated profile data found during page scrape
  1000. match = [item for count, item in enumerate(match) if item not in match[:count]]
  1001.  
  1002. if matchType == 1:
  1003. for p, t, e in match:
  1004. profile = {'name': unescape(p), 'token': t, 'isKids': e=='jfk'}
  1005. profiles.append(profile)
  1006. elif matchType == 2:
  1007. for e, t, p in match:
  1008. profile = {'name': unescape(p), 'token': t, 'isKids': e=='jfk'}
  1009. profiles.append(profile)
  1010.  
  1011. if matchType > 0:
  1012. dialog = xbmcgui.Dialog()
  1013. nr = dialog.select(translation(30113), [profile['name'] for profile in profiles])
  1014. if nr >= 0:
  1015. selectedProfile = profiles[nr]
  1016. else:
  1017. selectedProfile = profiles[0]
  1018. load("https://api-global.netflix.com/desktop/account/profiles/switch?switchProfileGuid="+selectedProfile['token'])
  1019. addon.setSetting("profile", selectedProfile['token'])
  1020. addon.setSetting("isKidsProfile", 'true' if selectedProfile['isKids'] else 'false')
  1021. addon.setSetting("profileName", selectedProfile['name'])
  1022. saveState()
  1023. getMyListChangeAuthorisation()
  1024. else:
  1025. debug("Netflixbmc::chooseProfile: No profiles were found")
  1026.  
  1027. def getMyListChangeAuthorisation():
  1028. content = load(urlMain+"/WiHome")
  1029. match = re.compile('"xsrf":"(.+?)"', re.DOTALL).findall(content)
  1030. if match:
  1031. authMyList = match[0]
  1032. addon.setSetting("authMyList", match[0])
  1033.  
  1034. def forceChooseProfile():
  1035. addon.setSetting("singleProfile", "false")
  1036. xbmc.executebuiltin('XBMC.Notification(NetfliXBMC:,'+str(translation(30111))+',5000,'+icon+')')
  1037. chooseProfile()
  1038.  
  1039.  
  1040. def addMovieToLibrary(movieID, title, singleUpdate=True):
  1041. movieFolderName = clean_filename(title+".strm", ' .').strip(' .')
  1042. dirAndFilename = os.path.join(libraryFolderMovies, movieFolderName)
  1043. fh = xbmcvfs.File(dirAndFilename, 'w')
  1044. fh.write("plugin://plugin.video.netflixbmc/?mode=playVideo&url="+movieID)
  1045. fh.close()
  1046. if updateDB and singleUpdate:
  1047. xbmc.executebuiltin('UpdateLibrary(video)')
  1048.  
  1049.  
  1050. def addSeriesToLibrary(seriesID, seriesTitle, season, singleUpdate=True):
  1051. seriesFolderName = clean_filename(seriesTitle, ' .')
  1052. seriesDir = os.path.join(libraryFolderTV, seriesFolderName)
  1053. if not os.path.isdir(seriesDir):
  1054. xbmcvfs.mkdir(seriesDir)
  1055. content = getSeriesInfo(seriesID)
  1056. content = json.loads(content)
  1057. for test in content["episodes"]:
  1058. for item in test:
  1059. episodeSeason = str(item["season"])
  1060. seasonCheck = True
  1061. if season:
  1062. seasonCheck = episodeSeason == season
  1063. if seasonCheck:
  1064. seasonDir = os.path.join(seriesDir, "Season "+episodeSeason)
  1065. if not os.path.isdir(seasonDir):
  1066. xbmcvfs.mkdir(seasonDir)
  1067. episodeID = str(item["episodeId"])
  1068. episodeNr = str(item["episode"])
  1069. episodeTitle = item["title"].encode('utf-8')
  1070. if len(episodeNr) == 1:
  1071. episodeNr = "0"+episodeNr
  1072. seasonNr = episodeSeason
  1073. if len(seasonNr) == 1:
  1074. seasonNr = "0"+seasonNr
  1075. filename = "S"+seasonNr+"E"+episodeNr+" - "+episodeTitle+".strm"
  1076. filename = clean_filename(filename, ' .')
  1077. fh = xbmcvfs.File(os.path.join(seasonDir, filename), 'w')
  1078. fh.write("plugin://plugin.video.netflixbmc/?mode=playVideo&url="+episodeID)
  1079. fh.close()
  1080. if updateDB and singleUpdate:
  1081. xbmc.executebuiltin('UpdateLibrary(video)')
  1082.  
  1083.  
  1084. def playTrailer(title):
  1085. try:
  1086. content = load("http://gdata.youtube.com/feeds/api/videos?vq="+title.strip().replace(" ", "+")+"+trailer&racy=include&orderby=relevance")
  1087. match = re.compile('<id>http://gdata.youtube.com/feeds/api/videos/(.+?)</id>', re.DOTALL).findall(content.split('<entry>')[2])
  1088. xbmc.Player().play("plugin://plugin.video.youtube/play/?video_id=" + match[0])
  1089. except:
  1090. pass
  1091.  
  1092.  
  1093. def translation(id):
  1094. return addon.getLocalizedString(id).encode('utf-8')
  1095.  
  1096.  
  1097. def parameters_string_to_dict(parameters):
  1098. paramDict = {}
  1099. if parameters:
  1100. paramPairs = parameters[1:].split("&")
  1101. for paramsPair in paramPairs:
  1102. paramSplits = paramsPair.split('=')
  1103. if (len(paramSplits)) == 2:
  1104. paramDict[paramSplits[0]] = paramSplits[1]
  1105. return paramDict
  1106.  
  1107.  
  1108. def addDir(name, url, mode, iconimage, type="", contextEnable=True):
  1109. name = htmlParser.unescape(name)
  1110. u = sys.argv[0]+"?url="+urllib.quote_plus(url)+"&mode="+str(mode)+"&type="+str(type)+"&thumb="+urllib.quote_plus(iconimage)
  1111. ok = True
  1112.  
  1113. liz = xbmcgui.ListItem(name, iconImage="DefaultTVShows.png", thumbnailImage=iconimage)
  1114. liz.setInfo(type="video", infoLabels={"title": name})
  1115. entries = []
  1116. if "/MyList" in url:
  1117. entries.append((translation(30122), 'RunPlugin(plugin://plugin.video.netflixbmc/?mode=addMyListToLibrary)',))
  1118. liz.setProperty("fanart_image", defaultFanart)
  1119. if contextEnable:
  1120. liz.addContextMenuItems(entries)
  1121. else:
  1122. emptyEntries = []
  1123. liz.addContextMenuItems(emptyEntries, replaceItems=True)
  1124. ok = xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]), url=u, listitem=liz, isFolder=True)
  1125. return ok
  1126.  
  1127.  
  1128. def addVideoDir(name, url, mode, iconimage, videoType="", desc="", duration="", year="", mpaa="", director="", genre="", rating=""):
  1129. ## if duration:
  1130. ## duration = str(int(duration) * 60)
  1131. name = name.encode("utf-8")
  1132. filename = clean_filename(url)+".jpg"
  1133. coverFile = os.path.join(cacheFolderCoversTMDB, filename)
  1134. fanartFile = os.path.join(cacheFolderFanartTMDB, filename)
  1135. if os.path.exists(coverFile):
  1136. iconimage = coverFile
  1137. u = sys.argv[0]+"?url="+urllib.quote_plus(url)+"&mode="+str(mode)+"&name="+urllib.quote_plus(name)+"&thumb="+urllib.quote_plus(iconimage)
  1138. ok = True
  1139. liz = xbmcgui.ListItem(name, iconImage="DefaultTVShows.png", thumbnailImage=iconimage)
  1140. liz.setInfo(type="video", infoLabels={"title": name, "plot": desc, "duration": duration, "year": year, "mpaa": mpaa, "director": director, "genre": genre, "rating": float(rating)})
  1141. if os.path.exists(fanartFile):
  1142. liz.setProperty("fanart_image", fanartFile)
  1143. elif os.path.exists(coverFile):
  1144. liz.setProperty("fanart_image", coverFile)
  1145. entries = []
  1146. if videoType == "tvshow":
  1147. if browseTvShows:
  1148. entries.append((translation(30121), 'Container.Update(plugin://plugin.video.netflixbmc/?mode=playVideoMain&url='+urllib.quote_plus(url)+'&thumb='+urllib.quote_plus(iconimage)+')',))
  1149. else:
  1150. entries.append((translation(30118), 'Container.Update(plugin://plugin.video.netflixbmc/?mode=listSeasons&url='+urllib.quote_plus(url)+'&thumb='+urllib.quote_plus(iconimage)+')',))
  1151. if videoType != "episode":
  1152. entries.append((translation(30134), 'RunPlugin(plugin://plugin.video.netflixbmc/?mode=playTrailer&url='+urllib.quote_plus(name)+')',))
  1153. entries.append((translation(30114), 'RunPlugin(plugin://plugin.video.netflixbmc/?mode=addToQueue&url='+urllib.quote_plus(url)+')',))
  1154. entries.append((translation(30140), 'Container.Update(plugin://plugin.video.netflixbmc/?mode=listVideos&url='+urllib.quote_plus(urlMain+"/WiMovie/"+url)+'&type=movie)',))
  1155. entries.append((translation(30141), 'Container.Update(plugin://plugin.video.netflixbmc/?mode=listVideos&url='+urllib.quote_plus(urlMain+"/WiMovie/"+url)+'&type=tv)',))
  1156. if videoType == "tvshow":
  1157. entries.append((translation(30122), 'RunPlugin(plugin://plugin.video.netflixbmc/?mode=addSeriesToLibrary&url=&name='+urllib.quote_plus(name.strip())+'&seriesID='+urllib.quote_plus(url)+')',))
  1158. elif videoType == "movie":
  1159. entries.append((translation(30122), 'RunPlugin(plugin://plugin.video.netflixbmc/?mode=addMovieToLibrary&url='+urllib.quote_plus(url)+'&name='+urllib.quote_plus(name.strip()+' ('+year+')')+')',))
  1160. liz.addContextMenuItems(entries)
  1161. ok = xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]), url=u, listitem=liz, isFolder=True)
  1162. return ok
  1163.  
  1164.  
  1165. def addVideoDirR(name, url, mode, iconimage, videoType="", desc="", duration="", year="", mpaa="", director="", genre="", rating=""):
  1166. ## if duration:
  1167. ## duration = str(int(duration) * 60)
  1168. name = name.encode("utf-8")
  1169. filename = clean_filename(url)+".jpg"
  1170. coverFile = os.path.join(cacheFolderCoversTMDB, filename)
  1171. fanartFile = os.path.join(cacheFolderFanartTMDB, filename)
  1172. if os.path.exists(coverFile):
  1173. iconimage = coverFile
  1174. u = sys.argv[0]+"?url="+urllib.quote_plus(url)+"&mode="+str(mode)+"&name="+urllib.quote_plus(name)+"&thumb="+urllib.quote_plus(iconimage)
  1175. ok = True
  1176. liz = xbmcgui.ListItem(name, iconImage="DefaultTVShows.png", thumbnailImage=iconimage)
  1177. liz.setInfo(type="video", infoLabels={"title": name, "plot": desc, "duration": duration, "year": year, "mpaa": mpaa, "director": director, "genre": genre, "rating": float(rating)})
  1178. if os.path.exists(fanartFile):
  1179. liz.setProperty("fanart_image", fanartFile)
  1180. elif os.path.exists(coverFile):
  1181. liz.setProperty("fanart_image", coverFile)
  1182. entries = []
  1183. if videoType == "tvshow":
  1184. if browseTvShows:
  1185. entries.append((translation(30121), 'Container.Update(plugin://plugin.video.netflixbmc/?mode=playVideoMain&url='+urllib.quote_plus(url)+'&thumb='+urllib.quote_plus(iconimage)+')',))
  1186. else:
  1187. entries.append((translation(30118), 'Container.Update(plugin://plugin.video.netflixbmc/?mode=listSeasons&url='+urllib.quote_plus(url)+'&thumb='+urllib.quote_plus(iconimage)+')',))
  1188. entries.append((translation(30134), 'RunPlugin(plugin://plugin.video.netflixbmc/?mode=playTrailer&url='+urllib.quote_plus(name)+')',))
  1189. entries.append((translation(30115), 'RunPlugin(plugin://plugin.video.netflixbmc/?mode=removeFromQueue&url='+urllib.quote_plus(url)+')',))
  1190. entries.append((translation(30140), 'Container.Update(plugin://plugin.video.netflixbmc/?mode=listVideos&url='+urllib.quote_plus(urlMain+"/WiMovie/"+url)+'&type=movie)',))
  1191. entries.append((translation(30141), 'Container.Update(plugin://plugin.video.netflixbmc/?mode=listVideos&url='+urllib.quote_plus(urlMain+"/WiMovie/"+url)+'&type=tv)',))
  1192. if videoType == "tvshow":
  1193. entries.append((translation(30122), 'RunPlugin(plugin://plugin.video.netflixbmc/?mode=addSeriesToLibrary&url=&name='+str(name.strip())+'&seriesID='+str(url)+')',))
  1194. elif videoType == "movie":
  1195. entries.append((translation(30122), 'RunPlugin(plugin://plugin.video.netflixbmc/?mode=addMovieToLibrary&url='+urllib.quote_plus(url)+'&name='+str(name.strip()+' ('+year+')')+')',))
  1196. liz.addContextMenuItems(entries)
  1197. ok = xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]), url=u, listitem=liz, isFolder=True)
  1198. return ok
  1199.  
  1200.  
  1201. def addSeasonDir(name, url, mode, iconimage, seriesName, seriesID):
  1202. filename = clean_filename(seriesID)+".jpg"
  1203. fanartFile = os.path.join(cacheFolderFanartTMDB, filename)
  1204. coverFile = os.path.join(cacheFolderCoversTMDB, filename)
  1205. u = sys.argv[0]+"?url="+urllib.quote_plus(url)+"&mode="+str(mode)+"&seriesID="+urllib.quote_plus(seriesID)
  1206. ok = True
  1207. liz = xbmcgui.ListItem(name, iconImage="DefaultTVShows.png", thumbnailImage=iconimage)
  1208. liz.setInfo(type="video", infoLabels={"title": name})
  1209. if os.path.exists(fanartFile):
  1210. liz.setProperty("fanart_image", fanartFile)
  1211. elif os.path.exists(coverFile):
  1212. liz.setProperty("fanart_image", coverFile)
  1213. entries = []
  1214. entries.append((translation(30122), 'RunPlugin(plugin://plugin.video.netflixbmc/?mode=addSeriesToLibrary&url='+urllib.quote_plus(url)+'&name='+str(seriesName.strip())+'&seriesID='+str(seriesID)+')',))
  1215. liz.addContextMenuItems(entries)
  1216. ok = xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]), url=u, listitem=liz, isFolder=True)
  1217. return ok
  1218.  
  1219.  
  1220. def addEpisodeDir(name, url, mode, iconimage, desc="", duration="", season="", episodeNr="", seriesID="", playcount=""):
  1221. ## if duration:
  1222. ## duration = str(int(duration) * 60)
  1223. filename = clean_filename(seriesID)+".jpg"
  1224. fanartFile = os.path.join(cacheFolderFanartTMDB, filename)
  1225. coverFile = os.path.join(cacheFolderCoversTMDB, filename)
  1226. u = sys.argv[0]+"?url="+urllib.quote_plus(url)+"&mode="+str(mode)
  1227. ok = True
  1228. liz = xbmcgui.ListItem(name, iconImage="DefaultTVShows.png", thumbnailImage=iconimage)
  1229. liz.setInfo(type="video", infoLabels={"title": name, "plot": desc, "duration": duration, "season": season, "episode": episodeNr, "playcount": playcount})
  1230. if os.path.exists(fanartFile):
  1231. liz.setProperty("fanart_image", fanartFile)
  1232. elif os.path.exists(coverFile):
  1233. liz.setProperty("fanart_image", coverFile)
  1234. ok = xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]), url=u, listitem=liz, isFolder=True)
  1235. return ok
  1236.  
  1237.  
  1238. class window(xbmcgui.WindowXMLDialog):
  1239. def __init__(self, *args, **kwargs):
  1240. xbmcgui.WindowXMLDialog.__init__(self, *args, **kwargs)
  1241. self._stopEvent = threading.Event()
  1242. self._wakeUpThread = threading.Thread(target=self._wakeUpThreadProc)
  1243. self._wakeUpThread.start()
  1244.  
  1245. def _wakeUpThreadProc(self):
  1246. while not self._stopEvent.is_set():
  1247. if debug:
  1248. print "Netflixbmc: Sending wakeup to main UI to avoid idle/DPMS..."
  1249. xbmc.executebuiltin("playercontrol(wakeup)")
  1250. # bit of a hack above: wakeup is actually not a valid playercontrol argument,
  1251. # but there's no error printed if the argument isn't found and any playercontrol
  1252. # causes the DPMS/idle timeout to reset itself
  1253. self._stopEvent.wait(60)
  1254. if debug:
  1255. print "Netflixbmc: wakeup thread finishing."
  1256.  
  1257. def stopWakeupThread(self):
  1258. if debug:
  1259. print "Netflixbmc: stopping wakeup thread"
  1260. self._stopEvent.set()
  1261. self._wakeUpThread.join()
  1262.  
  1263. def close(self):
  1264. if debug:
  1265. print "Netflixbmc: closing dummy window"
  1266. self.stopWakeupThread()
  1267. xbmcgui.WindowXMLDialog.close(self)
  1268.  
  1269. def onAction(self, action):
  1270. ACTION_SELECT_ITEM = 7
  1271. ACTION_PARENT_DIR = 9
  1272. ACTION_PREVIOUS_MENU = 10
  1273. ACTION_PAUSE = 12
  1274. ACTION_STOP = 13
  1275. ACTION_SHOW_INFO = 11
  1276. ACTION_SHOW_GUI = 18
  1277. ACTION_MOVE_LEFT = 1
  1278. ACTION_MOVE_RIGHT = 2
  1279. ACTION_MOVE_UP = 3
  1280. ACTION_MOVE_DOWN = 4
  1281. ACTION_PLAYER_PLAY = 79
  1282. ACTION_VOLUME_UP = 88
  1283. ACTION_VOLUME_DOWN = 89
  1284. ACTION_MUTE = 91
  1285. ACTION_CONTEXT_MENU = 117
  1286. ACTION_BUILT_IN_FUNCTION = 122
  1287. KEY_BUTTON_BACK = 275
  1288. if not remoteControl and action != ACTION_BUILT_IN_FUNCTION:
  1289. # if we're not passing remote control actions, any non-autogenerated
  1290. # remote action that reaches here is a signal to close this dummy
  1291. # window as Chrome is gone
  1292. if debug:
  1293. print "Netflixbmc: Closing dummy window after action %d" % (action.getId())
  1294. self.close()
  1295. return
  1296.  
  1297. if osWin:
  1298. proc = subprocess.Popen('WMIC PROCESS get Caption', shell=True, stdout=subprocess.PIPE)
  1299. procAll = ""
  1300. for line in proc.stdout:
  1301. procAll+=line
  1302. if "chrome.exe" in procAll:
  1303. if action in [ACTION_SHOW_INFO, ACTION_SHOW_GUI, ACTION_STOP, ACTION_PARENT_DIR, ACTION_PREVIOUS_MENU, KEY_BUTTON_BACK]:
  1304. subprocess.Popen('"'+sendKeysPath+'"'+' sendKey=Close', shell=False)
  1305. self.close()
  1306. elif action==ACTION_SELECT_ITEM:
  1307. subprocess.Popen('"'+sendKeysPath+'"'+' sendKey=PlayPause', shell=False)
  1308. elif action==ACTION_MOVE_LEFT:
  1309. subprocess.Popen('"'+sendKeysPath+'"'+' sendKey=SeekLeft', shell=False)
  1310. elif action==ACTION_MOVE_RIGHT:
  1311. subprocess.Popen('"'+sendKeysPath+'"'+' sendKey=SeekRight', shell=False)
  1312. elif action==ACTION_MOVE_UP:
  1313. subprocess.Popen('"'+sendKeysPath+'"'+' sendKey=VolumeUp', shell=False)
  1314. elif action==ACTION_MOVE_DOWN:
  1315. subprocess.Popen('"'+sendKeysPath+'"'+' sendKey=VolumeDown', shell=False)
  1316. else:
  1317. self.close()
  1318. elif osLinux:
  1319. doClose = False
  1320. key=None
  1321. if action in [ACTION_SHOW_GUI, ACTION_STOP, ACTION_PARENT_DIR, ACTION_PREVIOUS_MENU, KEY_BUTTON_BACK]:
  1322. key="control+shift+q"
  1323. doClose=True
  1324. elif action in [ ACTION_SELECT_ITEM, ACTION_PLAYER_PLAY, ACTION_PAUSE ]:
  1325. key="space"
  1326. elif action==ACTION_MOVE_LEFT:
  1327. key="Left"
  1328. elif action==ACTION_MOVE_RIGHT:
  1329. key="Right"
  1330. elif action==ACTION_SHOW_INFO:
  1331. key="question"
  1332. elif action==ACTION_VOLUME_UP:
  1333. key="Up"
  1334. elif action==ACTION_VOLUME_DOWN:
  1335. key="Down"
  1336. elif action==ACTION_MUTE:
  1337. key="M"
  1338. elif action==ACTION_CONTEXT_MENU:
  1339. key="ctrl+alt+shift+d"
  1340. elif debug:
  1341. print "Netflixbmc: unmapped key action=%d" % (action.getId())
  1342. if key is not None:
  1343. p = subprocess.Popen('xdotool search --onlyvisible --class "google-chrome|Chromium" key %s' % key, shell=True)
  1344. p.wait()
  1345. # 0 for success, 127 if xdotool not found in PATH. Return code is 1 if window not found (indicating should close).
  1346. if not p.returncode in [0,127] or doClose:
  1347. self.close()
  1348. if debug:
  1349. print "Netflixbmc: remote action=%d key=%s xdotool result=%d" % (action.getId(), key, p.returncode)
  1350. elif osOSX:
  1351. proc = subprocess.Popen('/bin/ps ax', shell=True, stdout=subprocess.PIPE)
  1352. procAll = ""
  1353. for line in proc.stdout:
  1354. procAll+=line
  1355. if "chrome" in procAll:
  1356. if action in [ACTION_SHOW_INFO, ACTION_SHOW_GUI, ACTION_STOP, ACTION_PARENT_DIR, ACTION_PREVIOUS_MENU, KEY_BUTTON_BACK]:
  1357. subprocess.Popen('cliclick kd:cmd t:q ku:cmd', shell=True)
  1358. self.close()
  1359. elif action==ACTION_SELECT_ITEM:
  1360. subprocess.Popen('cliclick t:p', shell=True)
  1361. elif action==ACTION_MOVE_LEFT:
  1362. subprocess.Popen('cliclick kp:arrow-left', shell=True)
  1363. elif action==ACTION_MOVE_RIGHT:
  1364. subprocess.Popen('cliclick kp:arrow-right', shell=True)
  1365. elif action==ACTION_MOVE_UP:
  1366. subprocess.Popen('cliclick kp:arrow-up', shell=True)
  1367. elif action==ACTION_MOVE_DOWN:
  1368. subprocess.Popen('cliclick kp:arrow-down', shell=True)
  1369. else:
  1370. self.close()
  1371. elif osAndroid:
  1372. pass #I don't know if we can do this on android, We also may not need to as the netflix app should respond to remotes
  1373.  
  1374.  
  1375. params = parameters_string_to_dict(sys.argv[2])
  1376. mode = urllib.unquote_plus(params.get('mode', ''))
  1377. url = urllib.unquote_plus(params.get('url', ''))
  1378. thumb = urllib.unquote_plus(params.get('thumb', ''))
  1379. name = urllib.unquote_plus(params.get('name', ''))
  1380. season = urllib.unquote_plus(params.get('season', ''))
  1381. seriesID = urllib.unquote_plus(params.get('seriesID', ''))
  1382. type = urllib.unquote_plus(params.get('type', ''))
  1383.  
  1384. #if the addon is requested from the homewindow, assume the content is retrieved as widget so disable progress bar and forcedviews
  1385. runAsWidget = urllib.unquote_plus(params.get('widget', '')) == 'true'
  1386.  
  1387. if mode == 'main':
  1388. main(type)
  1389. elif mode == 'wiHome':
  1390. wiHome(type)
  1391. elif mode == 'listVideos':
  1392. listVideos(url, type, runAsWidget)
  1393. elif mode == 'listSliderVideos':
  1394. listSliderVideos(url, type, runAsWidget)
  1395. elif mode == 'listSearchVideos':
  1396. listSearchVideos(url, type, runAsWidget)
  1397. elif mode == 'addToQueue':
  1398. addToQueue(url)
  1399. elif mode == 'removeFromQueue':
  1400. removeFromQueue(url)
  1401. elif mode == 'playVideo':
  1402. playVideo(url)
  1403. elif mode == 'playVideoMain':
  1404. playVideoMain(url)
  1405. elif mode == 'search':
  1406. search(type)
  1407. elif mode == 'login':
  1408. login()
  1409. elif mode == 'chooseProfile':
  1410. chooseProfile()
  1411. elif mode == 'listGenres':
  1412. listGenres(url, type)
  1413. elif mode == 'listTvGenres':
  1414. listTvGenres(type)
  1415. elif mode == 'listViewingActivity':
  1416. listViewingActivity(type, runAsWidget)
  1417. elif mode == 'listSeasons':
  1418. listSeasons(name, url, thumb)
  1419. elif mode == 'listEpisodes':
  1420. listEpisodes(seriesID, url)
  1421. elif mode == 'configureUtility':
  1422. configureUtility()
  1423. elif mode == 'chromePluginOptions':
  1424. chromePluginOptions()
  1425. elif mode == 'deleteCookies':
  1426. deleteCookies()
  1427. elif mode == 'deleteCache':
  1428. deleteCache()
  1429. elif mode == 'deleteChromeUserData':
  1430. deleteChromeUserDataFolder()
  1431. elif mode == 'resetAddon':
  1432. resetAddon()
  1433. elif mode == 'playTrailer':
  1434. playTrailer(url)
  1435. elif mode == 'addMyListToLibrary':
  1436. addMyListToLibrary()
  1437. elif mode == 'addMovieToLibrary':
  1438. addMovieToLibrary(url, name)
  1439. elif mode == 'addSeriesToLibrary':
  1440. addSeriesToLibrary(seriesID, name, url)
  1441. elif mode == 'profileDisplayUpdate':
  1442. profileDisplayUpdate()
  1443. else:
  1444. index()
  1445.  
  1446.  
  1447. if trace_on:
  1448. pydevd.stoptrace()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement