422 lines
20 KiB
Python
422 lines
20 KiB
Python
import xbmc
|
|
import xbmcgui
|
|
import xbmcaddon
|
|
import urllib
|
|
import urllib2
|
|
import httplib
|
|
import requests
|
|
import hashlib
|
|
import StringIO
|
|
import gzip
|
|
import sys
|
|
import json as json
|
|
from random import randrange
|
|
from uuid import getnode as get_mac
|
|
from ClientInformation import ClientInformation
|
|
|
|
class DownloadUtils():
|
|
|
|
logLevel = 0
|
|
addonSettings = None
|
|
getString = None
|
|
|
|
def __init__(self, *args):
|
|
self.addonSettings = xbmcaddon.Addon(id='plugin.video.xbmb3c')
|
|
self.getString = self.addonSettings.getLocalizedString
|
|
level = self.addonSettings.getSetting('logLevel')
|
|
self.logLevel = 0
|
|
if(level != None):
|
|
self.logLevel = int(level)
|
|
|
|
def logMsg(self, msg, level = 1):
|
|
if(self.logLevel >= level):
|
|
xbmc.log("XBMB3C DownloadUtils -> " + msg)
|
|
|
|
def getUserId(self):
|
|
|
|
port = self.addonSettings.getSetting('port')
|
|
host = self.addonSettings.getSetting('ipaddress')
|
|
userName = self.addonSettings.getSetting('username')
|
|
|
|
self.logMsg("Looking for user name: " + userName)
|
|
|
|
jsonData = None
|
|
try:
|
|
jsonData = self.downloadUrl(host + ":" + port + "/mediabrowser/Users/Public?format=json")
|
|
except Exception, msg:
|
|
error = "Get User unable to connect to " + host + ":" + port + " : " + str(msg)
|
|
xbmc.log (error)
|
|
return ""
|
|
|
|
|
|
self.logMsg("GETUSER_JSONDATA_01:" + str(jsonData))
|
|
|
|
result = []
|
|
|
|
try:
|
|
result = json.loads(jsonData)
|
|
except Exception, e:
|
|
self.logMsg("jsonload : " + str(e) + " (" + jsonData + ")", level=1)
|
|
return ""
|
|
|
|
self.logMsg("GETUSER_JSONDATA_02:" + str(result))
|
|
|
|
userid = ""
|
|
secure = False
|
|
for user in result:
|
|
if(user.get("Name") == userName):
|
|
userid = user.get("Id")
|
|
self.logMsg("Username Found:" + user.get("Name"))
|
|
if(user.get("HasPassword") == True):
|
|
secure = True
|
|
self.logMsg("Username Is Secure (HasPassword=True)")
|
|
break
|
|
|
|
if(secure):
|
|
self.authenticate('http://' + host + ":" + port + "/mediabrowser/Users/AuthenticateByName?format=json")
|
|
|
|
if userid == "":
|
|
return_value = xbmcgui.Dialog().ok(self.getString(30045),self.getString(30045))
|
|
sys.exit()
|
|
|
|
self.logMsg("userid : " + userid)
|
|
|
|
WINDOW = xbmcgui.Window( 10000 )
|
|
WINDOW.setProperty("userid", userid)
|
|
|
|
return userid
|
|
|
|
def getMachineId(self):
|
|
return "%012X"%get_mac()
|
|
|
|
def authenticate(self, url):
|
|
txt_mac = self.getMachineId()
|
|
version = ClientInformation().getVersion()
|
|
|
|
deviceName = self.addonSettings.getSetting('deviceName')
|
|
deviceName = deviceName.replace("\"", "_")
|
|
|
|
authString = "Mediabrowser Client=\"XBMC\",Device=\"" + deviceName + "\",DeviceId=\"" + txt_mac + "\",Version=\"" + version + "\""
|
|
headers = {'Accept-encoding': 'gzip', 'Authorization' : authString}
|
|
sha1 = hashlib.sha1(self.addonSettings.getSetting('password'))
|
|
resp = requests.post(url, data={'password':sha1.hexdigest(),'Username':self.addonSettings.getSetting('username')}, headers=headers)
|
|
code=str(resp.status_code)
|
|
result = resp.json()
|
|
if result.get("AccessToken") != self.addonSettings.getSetting('AccessToken'):
|
|
self.addonSettings.setSetting('AccessToken', result.get("AccessToken"))
|
|
if int(code) >= 200 and int(code)<300:
|
|
self.logMsg("User Authenticated")
|
|
else:
|
|
self.logMsg("User NOT Authenticated")
|
|
return_value = xbmcgui.Dialog().ok(self.getString(30044), self.getString(30044))
|
|
sys.exit()
|
|
|
|
def getArtwork(self, data, type, index = "0", userParentInfo = False):
|
|
|
|
id = data.get("Id")
|
|
getSeriesData = False
|
|
|
|
if type == "tvshow.poster": # Change the Id to the series to get the overall series poster
|
|
if data.get("Type") == "Season" or data.get("Type")== "Episode":
|
|
id = data.get("SeriesId")
|
|
getSeriesData = True
|
|
elif type == "poster" and data.get("Type") == "Episode" and self.addonSettings.getSetting('useSeasonPoster')=='true': # Change the Id to the Season to get the season poster
|
|
id = data.get("SeasonId")
|
|
if type == "poster" or type == "tvshow.poster": # Now that the Ids are right, change type to MB3 name
|
|
type="Primary"
|
|
if data.get("Type") == "Season": # For seasons: primary (poster), thumb and banner get season art, rest series art
|
|
if type != "Primary" and type != "Thumb" and type != "Banner":
|
|
id = data.get("SeriesId")
|
|
getSeriesData = True
|
|
if data.get("Type") == "Episode": # For episodes: primary (episode thumb) gets episode art, rest series art.
|
|
if type != "Primary":
|
|
id = data.get("SeriesId")
|
|
getSeriesData = True
|
|
|
|
# if requested get parent info
|
|
if getSeriesData == True and userParentInfo == True:
|
|
self.logMsg("Using Parent Info for image link", level=1)
|
|
mb3Host = self.addonSettings.getSetting('ipaddress')
|
|
mb3Port = self.addonSettings.getSetting('port')
|
|
userid = self.getUserId()
|
|
seriesJsonData = self.downloadUrl("http://" + mb3Host + ":" + mb3Port + "/mediabrowser/Users/" + userid + "/Items/" + id + "?format=json", suppress=False, popup=1 )
|
|
seriesResult = json.loads(seriesJsonData)
|
|
data = seriesResult
|
|
|
|
imageTag = "e3ab56fe27d389446754d0fb04910a34" # a place holder tag, needs to be in this format
|
|
originalType = type
|
|
if type == "Primary2" or type == "Primary3" or type=="SeriesPrimary":
|
|
type = "Primary"
|
|
if type == "Backdrop2" or type=="Backdrop3":
|
|
type = "Backdrop"
|
|
if type == "Thumb2" or type=="Thumb3":
|
|
type = "Thumb"
|
|
if(data.get("ImageTags") != None and data.get("ImageTags").get(type) != None):
|
|
imageTag = data.get("ImageTags").get(type)
|
|
|
|
query = ""
|
|
height = "10000"
|
|
width = "10000"
|
|
played = "0"
|
|
|
|
if self.addonSettings.getSetting('showIndicators')=='true': # add watched, unplayedcount and percentage played indicators to posters
|
|
|
|
if (originalType =="Primary" or originalType =="Backdrop") and data.get("Type") != "Episode":
|
|
userData = data.get("UserData")
|
|
if originalType =="Backdrop" and index == "0":
|
|
totalbackdrops = len(data.get("BackdropImageTags"))
|
|
if totalbackdrops != 0:
|
|
index = str(randrange(0,totalbackdrops))
|
|
if userData != None:
|
|
|
|
UnWatched = 0 if userData.get("UnplayedItemCount")==None else userData.get("UnplayedItemCount")
|
|
|
|
if UnWatched <> 0 and self.addonSettings.getSetting('showUnplayedIndicators')=='true':
|
|
query = query + "&UnplayedCount=" + str(UnWatched)
|
|
|
|
|
|
if(userData != None and userData.get("Played") == True and self.addonSettings.getSetting('showWatchedIndicators')=='true'):
|
|
query = query + "&AddPlayedIndicator=true"
|
|
|
|
PlayedPercentage = 0 if userData.get("PlayedPercentage")==None else userData.get("PlayedPercentage")
|
|
if PlayedPercentage == 0 and userData!=None and userData.get("PlayedPercentage")!=None :
|
|
PlayedPercentage = userData.get("PlayedPercentage")
|
|
if (PlayedPercentage != 100 or PlayedPercentage) != 0 and self.addonSettings.getSetting('showPlayedPrecentageIndicators')=='true':
|
|
played = str(PlayedPercentage)
|
|
|
|
elif originalType =="Primary2" and data.get("Type") != "Episode":
|
|
userData = data.get("UserData")
|
|
if userData != None:
|
|
|
|
UnWatched = 0 if userData.get("UnplayedItemCount")==None else userData.get("UnplayedItemCount")
|
|
|
|
if UnWatched <> 0 and self.addonSettings.getSetting('showUnplayedIndicators')=='true':
|
|
query = query + "&UnplayedCount=" + str(UnWatched)
|
|
|
|
if(userData != None and userData.get("Played") == True and self.addonSettings.getSetting('showWatchedIndicators')=='true'):
|
|
query = query + "&AddPlayedIndicator=true"
|
|
|
|
PlayedPercentage = 0 if userData.get("PlayedPercentage")==None else userData.get("PlayedPercentage")
|
|
if PlayedPercentage == 0 and userData!=None and userData.get("PlayedPercentage")!=None :
|
|
PlayedPercentage = userData.get("PlayedPercentage")
|
|
if (PlayedPercentage != 100 or PlayedPercentage) != 0 and self.addonSettings.getSetting('showPlayedPrecentageIndicators')=='true':
|
|
played = str(PlayedPercentage)
|
|
|
|
height = "340"
|
|
width = "226"
|
|
|
|
elif (originalType =="Primary3" and data.get("Type") != "Episode") or originalType == "SeriesPrimary":
|
|
userData = data.get("UserData")
|
|
if userData != None:
|
|
|
|
UnWatched = 0 if userData.get("UnplayedItemCount")==None else userData.get("UnplayedItemCount")
|
|
|
|
if UnWatched <> 0 and self.addonSettings.getSetting('showUnplayedIndicators')=='true':
|
|
query = query + "&UnplayedCount=" + str(UnWatched)
|
|
|
|
if(userData != None and userData.get("Played") == True and self.addonSettings.getSetting('showWatchedIndicators')=='true'):
|
|
query = query + "&AddPlayedIndicator=true"
|
|
|
|
PlayedPercentage = 0 if userData.get("PlayedPercentage")==None else userData.get("PlayedPercentage")
|
|
if PlayedPercentage == 0 and userData!=None and userData.get("PlayedPercentage")!=None :
|
|
PlayedPercentage = userData.get("PlayedPercentage")
|
|
if (PlayedPercentage != 100 or PlayedPercentage) != 0 and self.addonSettings.getSetting('showPlayedPrecentageIndicators')=='true':
|
|
played = str(PlayedPercentage)
|
|
|
|
height = "800"
|
|
width = "550"
|
|
|
|
elif type =="Primary" and data.get("Type") == "Episode":
|
|
userData = data.get("UserData")
|
|
if userData != None:
|
|
|
|
UnWatched = 0 if userData.get("UnplayedItemCount")==None else userData.get("UnplayedItemCount")
|
|
|
|
if UnWatched <> 0 and self.addonSettings.getSetting('showUnplayedIndicators')=='true':
|
|
query = query + "&UnplayedCount=" + str(UnWatched)
|
|
|
|
if(userData != None and userData.get("Played") == True and self.addonSettings.getSetting('showWatchedIndicators')=='true'):
|
|
query = query + "&AddPlayedIndicator=true"
|
|
|
|
PlayedPercentage = 0 if userData.get("PlayedPercentage")==None else userData.get("PlayedPercentage")
|
|
if PlayedPercentage == 0 and userData!=None and userData.get("PlayedPercentage")!=None :
|
|
PlayedPercentage = userData.get("PlayedPercentage")
|
|
if (PlayedPercentage != 100 or PlayedPercentage) != 0 and self.addonSettings.getSetting('showPlayedPrecentageIndicators')=='true':
|
|
played = str(PlayedPercentage)
|
|
|
|
height = "410"
|
|
width = "770"
|
|
|
|
elif originalType =="Backdrop2" or originalType =="Thumb2" and data.get("Type") != "Episode":
|
|
userData = data.get("UserData")
|
|
if originalType =="Backdrop2":
|
|
totalbackdrops = len(data.get("BackdropImageTags"))
|
|
if totalbackdrops != 0:
|
|
index = str(randrange(0,totalbackdrops))
|
|
if userData != None:
|
|
|
|
UnWatched = 0 if userData.get("UnplayedItemCount")==None else userData.get("UnplayedItemCount")
|
|
|
|
if UnWatched <> 0 and self.addonSettings.getSetting('showUnplayedIndicators')=='true':
|
|
query = query + "&UnplayedCount=" + str(UnWatched)
|
|
|
|
if(userData != None and userData.get("Played") == True and self.addonSettings.getSetting('showWatchedIndicators')=='true'):
|
|
query = query + "&AddPlayedIndicator=true"
|
|
|
|
PlayedPercentage = 0 if userData.get("PlayedPercentage")==None else userData.get("PlayedPercentage")
|
|
if PlayedPercentage == 0 and userData!=None and userData.get("PlayedPercentage")!=None :
|
|
PlayedPercentage = userData.get("PlayedPercentage")
|
|
if (PlayedPercentage != 100 or PlayedPercentage) != 0 and self.addonSettings.getSetting('showPlayedPrecentageIndicators')=='true':
|
|
played = str(PlayedPercentage)
|
|
|
|
height = "270"
|
|
width = "480"
|
|
|
|
elif originalType =="Backdrop3" or originalType =="Thumb3" and data.get("Type") != "Episode":
|
|
userData = data.get("UserData")
|
|
if originalType =="Backdrop3":
|
|
totalbackdrops = len(data.get("BackdropImageTags"))
|
|
if totalbackdrops != 0:
|
|
index = str(randrange(0,totalbackdrops))
|
|
if userData != None:
|
|
|
|
UnWatched = 0 if userData.get("UnplayedItemCount")==None else userData.get("UnplayedItemCount")
|
|
|
|
if UnWatched <> 0 and self.addonSettings.getSetting('showUnplayedIndicators')=='true':
|
|
query = query + "&UnplayedCount=" + str(UnWatched)
|
|
|
|
if(userData != None and userData.get("Played") == True and self.addonSettings.getSetting('showWatchedIndicators')=='true'):
|
|
query = query + "&AddPlayedIndicator=true"
|
|
|
|
PlayedPercentage = 0 if userData.get("PlayedPercentage")==None else userData.get("PlayedPercentage")
|
|
if PlayedPercentage == 0 and userData!=None and userData.get("PlayedPercentage")!=None :
|
|
PlayedPercentage = userData.get("PlayedPercentage")
|
|
if (PlayedPercentage != 100 or PlayedPercentage) != 0 and self.addonSettings.getSetting('showPlayedPrecentageIndicators')=='true':
|
|
played = str(PlayedPercentage)
|
|
|
|
height = "800"
|
|
width = "1420"
|
|
|
|
# use the local image proxy server that is made available by this addons service
|
|
|
|
port = self.addonSettings.getSetting('port')
|
|
host = self.addonSettings.getSetting('ipaddress')
|
|
server = host + ":" + port
|
|
|
|
artwork = "http://" + server + "/mediabrowser/Items/" + str(id) + "/Images/" + type + "/" + index + "/" + imageTag + "/original/" + height + "/" + width + "/" + played + "?" + query
|
|
if self.addonSettings.getSetting('disableCoverArt')=='true':
|
|
artwork = artwork + "&EnableImageEnhancers=false"
|
|
|
|
self.logMsg("getArtwork : " + artwork, level=2)
|
|
|
|
# do not return non-existing images
|
|
if ( (type!="Backdrop" and imageTag=="") |
|
|
(type=="Backdrop" and data.get("BackdropImageTags") != None and len(data.get("BackdropImageTags")) == 0) |
|
|
(type=="Backdrop" and data.get("BackdropImageTag") != None and len(data.get("BackdropImageTag")) == 0)
|
|
):
|
|
if type=="Backdrop" and getSeriesData==True and data.get("ParentBackdropImageTags") == None:
|
|
artwork=''
|
|
|
|
return artwork
|
|
|
|
def getUserArtwork(self, data, type, index = "0"):
|
|
|
|
id = data.get("Id")
|
|
#query = "&type=" + type + "&tag=" + imageTag
|
|
query = ""
|
|
height = "60"
|
|
width = "60"
|
|
played = "0"
|
|
|
|
# use the local image proxy server that is made available by this addons service
|
|
port = self.addonSettings.getSetting('port')
|
|
host = self.addonSettings.getSetting('ipaddress')
|
|
server = host + ":" + port
|
|
|
|
artwork = "http://" + server + "/mediabrowser/Users/" + str(id) + "/Images/Primary/0" + "?height=60&width=60&format=png"
|
|
|
|
return artwork
|
|
|
|
def imageUrl(self, id, type, index, width, height):
|
|
|
|
port = self.addonSettings.getSetting('port')
|
|
host = self.addonSettings.getSetting('ipaddress')
|
|
server = host + ":" + port
|
|
|
|
return "http://" + server + "/mediabrowser/Items/" + str(id) + "/Images/" + type + "/" + str(index) + "/e3ab56fe27d389446754d0fb04910a34/original/" + str(height) + "/" + str(width) + "/0"
|
|
|
|
def downloadUrl(self, url, suppress=False, type="GET", popup=0 ):
|
|
self.logMsg("== ENTER: getURL ==")
|
|
try:
|
|
if url[0:4] == "http":
|
|
serversplit=2
|
|
urlsplit=3
|
|
else:
|
|
serversplit=0
|
|
urlsplit=1
|
|
|
|
server=url.split('/')[serversplit]
|
|
urlPath="/"+"/".join(url.split('/')[urlsplit:])
|
|
|
|
self.logMsg("url = " + url)
|
|
self.logMsg("server = "+str(server), level=2)
|
|
self.logMsg("urlPath = "+str(urlPath), level=2)
|
|
conn = httplib.HTTPConnection(server, timeout=20)
|
|
#head = {"Accept-Encoding" : "gzip,deflate", "Accept-Charset" : "UTF-8,*"}
|
|
if self.addonSettings.getSetting('AccessToken')==None:
|
|
self.addonSettings.setSetting('AccessToken','')
|
|
head = {"Accept-Encoding" : "gzip", "Accept-Charset" : "UTF-8,*", "X-MediaBrowser-Token" : self.addonSettings.getSetting('AccessToken')}
|
|
#head = getAuthHeader()
|
|
conn.request(method=type, url=urlPath, headers=head)
|
|
#conn.request(method=type, url=urlPath)
|
|
data = conn.getresponse()
|
|
self.logMsg("GET URL HEADERS : " + str(data.getheaders()), level=2)
|
|
link = ""
|
|
contentType = "none"
|
|
if int(data.status) == 200:
|
|
retData = data.read()
|
|
contentType = data.getheader('content-encoding')
|
|
self.logMsg("Data Len Before : " + str(len(retData)))
|
|
if(contentType == "gzip"):
|
|
retData = StringIO.StringIO(retData)
|
|
gzipper = gzip.GzipFile(fileobj=retData)
|
|
link = gzipper.read()
|
|
else:
|
|
link = retData
|
|
|
|
self.logMsg("Data Len After : " + str(len(link)))
|
|
self.logMsg("====== 200 returned =======")
|
|
self.logMsg("Content-Type : " + str(contentType))
|
|
self.logMsg(link)
|
|
self.logMsg("====== 200 finished ======")
|
|
|
|
elif ( int(data.status) == 301 ) or ( int(data.status) == 302 ):
|
|
try: conn.close()
|
|
except: pass
|
|
return data.getheader('Location')
|
|
|
|
elif int(data.status) >= 400:
|
|
error = "HTTP response error: " + str(data.status) + " " + str(data.reason)
|
|
xbmc.log (error)
|
|
if suppress is False:
|
|
if popup == 0:
|
|
xbmc.executebuiltin("XBMC.Notification(URL error: "+ str(data.reason) +",)")
|
|
else:
|
|
xbmcgui.Dialog().ok(self.getString(30135),server)
|
|
xbmc.log (error)
|
|
try: conn.close()
|
|
except: pass
|
|
return ""
|
|
else:
|
|
link = ""
|
|
except Exception, msg:
|
|
error = "Unable to connect to " + str(server) + " : " + str(msg)
|
|
xbmc.log (error)
|
|
xbmc.executebuiltin("XBMC.Notification(\"XBMB3C\": URL error: Unable to connect to server,)")
|
|
xbmcgui.Dialog().ok("",self.getString(30204))
|
|
raise
|
|
else:
|
|
try: conn.close()
|
|
except: pass
|
|
|
|
return link |