mirror of
https://github.com/jellyfin/jellyfin-kodi.git
synced 2024-11-10 04:06:11 +00:00
Pylint (#65)
websocket, artwork, api, service_entry, downloadutils, contextmenu
This commit is contained in:
parent
d61e872bf9
commit
d2b6eaabb3
5 changed files with 124 additions and 123 deletions
|
@ -127,8 +127,8 @@ class ContextMenu(object):
|
||||||
options.append(OPTIONS['Addon'])
|
options.append(OPTIONS['Addon'])
|
||||||
|
|
||||||
addon = xbmcaddon.Addon('plugin.video.emby')
|
addon = xbmcaddon.Addon('plugin.video.emby')
|
||||||
xml_path = (addon.getAddonInfo('path'), "default", "1080i")
|
context_menu = context.ContextMenu("script-emby-context.xml", addon.getAddonInfo('path'),
|
||||||
context_menu = context.ContextMenu("script-emby-context.xml", *xml_path)
|
"default", "1080i")
|
||||||
context_menu.set_options(options)
|
context_menu.set_options(options)
|
||||||
context_menu.doModal()
|
context_menu.doModal()
|
||||||
|
|
||||||
|
|
|
@ -3,8 +3,8 @@
|
||||||
##################################################################################################
|
##################################################################################################
|
||||||
|
|
||||||
import json
|
import json
|
||||||
import requests
|
|
||||||
import logging
|
import logging
|
||||||
|
import requests
|
||||||
|
|
||||||
import xbmcgui
|
import xbmcgui
|
||||||
|
|
||||||
|
@ -62,9 +62,9 @@ class DownloadUtils(object):
|
||||||
'Token': server['AccessToken'],
|
'Token': server['AccessToken'],
|
||||||
'SSL': ssl
|
'SSL': ssl
|
||||||
}
|
}
|
||||||
for s in self.servers:
|
for server_info in self.servers:
|
||||||
if s == server_id:
|
if server_info == server_id:
|
||||||
s.update(info)
|
server_info.update(info)
|
||||||
# Set window prop
|
# Set window prop
|
||||||
self._set_server_properties(server_id, server['Name'], info)
|
self._set_server_properties(server_id, server['Name'], info)
|
||||||
log.info("updating %s to available servers: %s", server_id, self.servers)
|
log.info("updating %s to available servers: %s", server_id, self.servers)
|
||||||
|
@ -89,7 +89,6 @@ class DownloadUtils(object):
|
||||||
window('emby_server%s.name' % server_id, value=name)
|
window('emby_server%s.name' % server_id, value=name)
|
||||||
|
|
||||||
def post_capabilities(self, device_id):
|
def post_capabilities(self, device_id):
|
||||||
|
|
||||||
# Post settings to session
|
# Post settings to session
|
||||||
url = "{server}/emby/Sessions/Capabilities/Full?format=json"
|
url = "{server}/emby/Sessions/Capabilities/Full?format=json"
|
||||||
data = {
|
data = {
|
||||||
|
@ -110,9 +109,6 @@ class DownloadUtils(object):
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
log.debug("capabilities URL: %s" % url)
|
|
||||||
log.debug("Postdata: %s" % data)
|
|
||||||
|
|
||||||
self.downloadUrl(url, postBody=data, action_type="POST")
|
self.downloadUrl(url, postBody=data, action_type="POST")
|
||||||
log.debug("Posted capabilities to %s" % self.session['Server'])
|
log.debug("Posted capabilities to %s" % self.session['Server'])
|
||||||
|
|
||||||
|
@ -120,46 +116,42 @@ class DownloadUtils(object):
|
||||||
url = "{server}/emby/Sessions?DeviceId=%s&format=json" % device_id
|
url = "{server}/emby/Sessions?DeviceId=%s&format=json" % device_id
|
||||||
result = self.downloadUrl(url)
|
result = self.downloadUrl(url)
|
||||||
try:
|
try:
|
||||||
sessionId = result[0]['Id']
|
session_id = result[0]['Id']
|
||||||
|
|
||||||
except (KeyError, TypeError):
|
except (KeyError, TypeError):
|
||||||
log.info("Failed to retrieve sessionId.")
|
log.error("Failed to retrieve the session id.")
|
||||||
|
|
||||||
else:
|
else:
|
||||||
log.debug("Session: %s" % result)
|
log.info("SessionId: %s", session_id)
|
||||||
log.info("SessionId: %s" % sessionId)
|
window('emby_sessionId', value=session_id)
|
||||||
window('emby_sessionId', value=sessionId)
|
|
||||||
|
|
||||||
# Post any permanent additional users
|
# Post any permanent additional users
|
||||||
additionalUsers = settings('additionalUsers')
|
additional_users = settings('additionalUsers')
|
||||||
if additionalUsers:
|
if additional_users:
|
||||||
|
|
||||||
additionalUsers = additionalUsers.split(',')
|
additional_users = additional_users.split(',')
|
||||||
log.info("List of permanent users added to the session: %s" % additionalUsers)
|
log.info("List of permanent users added to the session: %s", additional_users)
|
||||||
|
|
||||||
# Get the user list from server to get the userId
|
# Get the user list from server to get the userId
|
||||||
url = "{server}/emby/Users?format=json"
|
url = "{server}/emby/Users?format=json"
|
||||||
result = self.downloadUrl(url)
|
result = self.downloadUrl(url)
|
||||||
|
|
||||||
for additional in additionalUsers:
|
for additional in additional_users:
|
||||||
addUser = additional.decode('utf-8').lower()
|
add_user = additional.decode('utf-8').lower()
|
||||||
|
|
||||||
# Compare to server users to list of permanent additional users
|
# Compare to server users to list of permanent additional users
|
||||||
for user in result:
|
for user in result:
|
||||||
username = user['Name'].lower()
|
username = user['Name'].lower()
|
||||||
|
|
||||||
if username in addUser:
|
if username in add_user:
|
||||||
userId = user['Id']
|
user_id = user['Id']
|
||||||
url = (
|
url = ("{server}/emby/Sessions/%s/Users/%s?format=json"
|
||||||
"{server}/emby/Sessions/%s/Users/%s?format=json"
|
% (session_id, user_id))
|
||||||
% (sessionId, userId)
|
|
||||||
)
|
|
||||||
self.downloadUrl(url, postBody={}, action_type="POST")
|
self.downloadUrl(url, postBody={}, action_type="POST")
|
||||||
|
|
||||||
def start_session(self):
|
def start_session(self):
|
||||||
# User is identified from this point
|
# User is identified from this point
|
||||||
# Attach authenticated header to the session
|
# Attach authenticated header to the session
|
||||||
# Start session
|
|
||||||
session = requests.Session()
|
session = requests.Session()
|
||||||
session.headers = self.get_header()
|
session.headers = self.get_header()
|
||||||
session.verify = self.session['SSL']
|
session.verify = self.session['SSL']
|
||||||
|
@ -216,7 +208,6 @@ class DownloadUtils(object):
|
||||||
|
|
||||||
log.debug("===== ENTER downloadUrl =====")
|
log.debug("===== ENTER downloadUrl =====")
|
||||||
|
|
||||||
session = requests
|
|
||||||
kwargs = {}
|
kwargs = {}
|
||||||
default_link = ""
|
default_link = ""
|
||||||
|
|
||||||
|
@ -228,6 +219,7 @@ class DownloadUtils(object):
|
||||||
if server_id is None and self.session_requests is not None: # Main server
|
if server_id is None and self.session_requests is not None: # Main server
|
||||||
session = self.session_requests
|
session = self.session_requests
|
||||||
else:
|
else:
|
||||||
|
session = requests
|
||||||
kwargs.update({
|
kwargs.update({
|
||||||
'verify': server['SSL'],
|
'verify': server['SSL'],
|
||||||
'headers': self.get_header(server_id, authenticate)
|
'headers': self.get_header(server_id, authenticate)
|
||||||
|
@ -308,7 +300,8 @@ class DownloadUtils(object):
|
||||||
window('emby_serverStatus', value="restricted")
|
window('emby_serverStatus', value="restricted")
|
||||||
raise Warning('restricted')
|
raise Warning('restricted')
|
||||||
|
|
||||||
elif response.headers['X-Application-Error-Code'] == "UnauthorizedAccessException":
|
elif (response.headers['X-Application-Error-Code'] ==
|
||||||
|
"UnauthorizedAccessException"):
|
||||||
# User tried to do something his emby account doesn't allow
|
# User tried to do something his emby account doesn't allow
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
|
@ -42,6 +42,7 @@ class Player(xbmc.Player):
|
||||||
self.xbmcplayer = xbmc.Player()
|
self.xbmcplayer = xbmc.Player()
|
||||||
|
|
||||||
log.debug("Starting playback monitor.")
|
log.debug("Starting playback monitor.")
|
||||||
|
xbmc.Player.__init__(self)
|
||||||
|
|
||||||
|
|
||||||
def GetPlayStats(self):
|
def GetPlayStats(self):
|
||||||
|
|
|
@ -28,20 +28,18 @@ log = logging.getLogger("EMBY."+__name__)
|
||||||
|
|
||||||
class Service(object):
|
class Service(object):
|
||||||
|
|
||||||
welcome_msg = True
|
startup = False
|
||||||
server_online = True
|
server_online = True
|
||||||
warn_auth = True
|
warn_auth = True
|
||||||
|
|
||||||
userclient_running = False
|
userclient_running = False
|
||||||
userclient_thread = None
|
userclient_thread = None
|
||||||
|
|
||||||
websocket_running = False
|
websocket_running = False
|
||||||
websocket_thread = None
|
websocket_thread = None
|
||||||
|
|
||||||
library_running = False
|
library_running = False
|
||||||
library_thread = None
|
library_thread = None
|
||||||
|
|
||||||
monitor = False
|
last_progress = datetime.today()
|
||||||
|
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
@ -83,30 +81,29 @@ class Service(object):
|
||||||
|
|
||||||
|
|
||||||
def service_entry_point(self):
|
def service_entry_point(self):
|
||||||
|
|
||||||
# Important: Threads depending on abortRequest will not trigger
|
# Important: Threads depending on abortRequest will not trigger
|
||||||
# if profile switch happens more than once.
|
# if profile switch happens more than once.
|
||||||
self.monitor = kodimonitor.KodiMonitor()
|
self.monitor = kodimonitor.KodiMonitor()
|
||||||
kodiProfile = xbmc.translatePath('special://profile')
|
self.kodi_player = player.Player()
|
||||||
|
kodi_profile = xbmc.translatePath('special://profile')
|
||||||
|
|
||||||
# Server auto-detect
|
# Server auto-detect
|
||||||
initialsetup.InitialSetup().setup()
|
initialsetup.InitialSetup().setup()
|
||||||
|
|
||||||
# Initialize important threads
|
# Initialize important threads
|
||||||
self.userclient_thread = userclient.UserClient()
|
self.userclient_thread = userclient.UserClient()
|
||||||
|
user_client = self.userclient_thread
|
||||||
self.websocket_thread = wsc.WebSocketClient()
|
self.websocket_thread = wsc.WebSocketClient()
|
||||||
self.library_thread = librarysync.LibrarySync()
|
self.library_thread = librarysync.LibrarySync()
|
||||||
kplayer = player.Player()
|
|
||||||
# Sync and progress report
|
|
||||||
lastProgressUpdate = datetime.today()
|
|
||||||
|
|
||||||
while not self.monitor.abortRequested():
|
while not self.monitor.abortRequested():
|
||||||
|
|
||||||
if window('emby_kodiProfile') != kodiProfile:
|
if window('emby_kodiProfile') != kodi_profile:
|
||||||
# Profile change happened, terminate this thread and others
|
# Profile change happened, terminate this thread and others
|
||||||
log.info("Kodi profile was: %s and changed to: %s. Terminating old Emby thread.",
|
log.info("Kodi profile was: %s and changed to: %s. Terminating old Emby thread.",
|
||||||
kodiProfile, window('emby_kodiProfile'))
|
kodi_profile, window('emby_kodiProfile'))
|
||||||
break
|
raise RuntimeError("Kodi profile changed detected")
|
||||||
|
|
||||||
# Before proceeding, need to make sure:
|
# Before proceeding, need to make sure:
|
||||||
# 1. Server is online
|
# 1. Server is online
|
||||||
|
@ -117,69 +114,17 @@ class Service(object):
|
||||||
|
|
||||||
# Emby server is online
|
# Emby server is online
|
||||||
# Verify if user is set and has access to the server
|
# Verify if user is set and has access to the server
|
||||||
if self.userclient_thread.get_user() is not None and self.userclient_thread.get_access():
|
if user_client.get_user() is not None and user_client.get_access():
|
||||||
|
|
||||||
# If an item is playing
|
# If an item is playing
|
||||||
if xbmc.Player().isPlaying():
|
if self.kodi_player.isPlaying():
|
||||||
try:
|
self._report_progress()
|
||||||
# Update and report progress
|
|
||||||
playtime = xbmc.Player().getTime()
|
|
||||||
totalTime = xbmc.Player().getTotalTime()
|
|
||||||
currentFile = kplayer.currentFile
|
|
||||||
|
|
||||||
# Update positionticks
|
elif not self.startup:
|
||||||
if kplayer.played_info.get(currentFile) is not None:
|
self.startup = self._startup()
|
||||||
kplayer.played_info[currentFile]['currentPosition'] = playtime
|
|
||||||
|
|
||||||
td = datetime.today() - lastProgressUpdate
|
|
||||||
secDiff = td.seconds
|
|
||||||
|
|
||||||
# Report progress to Emby server
|
|
||||||
if (secDiff > 3):
|
|
||||||
kplayer.reportPlayback()
|
|
||||||
lastProgressUpdate = datetime.today()
|
|
||||||
|
|
||||||
elif window('emby_command') == "true":
|
|
||||||
# Received a remote control command that
|
|
||||||
# requires updating immediately
|
|
||||||
window('emby_command', clear=True)
|
|
||||||
kplayer.reportPlayback()
|
|
||||||
lastProgressUpdate = datetime.today()
|
|
||||||
|
|
||||||
except Exception:
|
|
||||||
log.exception("Exception in Playback Monitor Service")
|
|
||||||
else:
|
|
||||||
# Start up events
|
|
||||||
self.warn_auth = True
|
|
||||||
if settings('connectMsg') == "true" and self.welcome_msg:
|
|
||||||
# Reset authentication warnings
|
|
||||||
self.welcome_msg = False
|
|
||||||
# Get additional users
|
|
||||||
additionalUsers = settings('additionalUsers')
|
|
||||||
if additionalUsers:
|
|
||||||
add = ", %s" % ", ".join(additionalUsers.split(','))
|
|
||||||
else:
|
|
||||||
add = ""
|
|
||||||
dialog(type_="notification",
|
|
||||||
heading="{emby}",
|
|
||||||
message=("%s %s%s!"
|
|
||||||
% (lang(33000), self.userclient_thread.get_username().decode('utf-8'),
|
|
||||||
add.decode('utf-8'))),
|
|
||||||
icon="{emby}",
|
|
||||||
time=2000,
|
|
||||||
sound=False)
|
|
||||||
|
|
||||||
# Start the Websocket Client
|
|
||||||
if not self.websocket_running:
|
|
||||||
self.websocket_running = True
|
|
||||||
self.websocket_thread.start()
|
|
||||||
# Start the syncing thread
|
|
||||||
if not self.library_running:
|
|
||||||
self.library_running = True
|
|
||||||
self.library_thread.start()
|
|
||||||
else:
|
else:
|
||||||
|
|
||||||
if (self.userclient_thread.get_user() is None) and self.warn_auth:
|
if (user_client.get_user() is None) and self.warn_auth:
|
||||||
# Alert user is not authenticated and suppress future warning
|
# Alert user is not authenticated and suppress future warning
|
||||||
self.warn_auth = False
|
self.warn_auth = False
|
||||||
log.info("Not authenticated yet.")
|
log.info("Not authenticated yet.")
|
||||||
|
@ -187,16 +132,7 @@ class Service(object):
|
||||||
# User access is restricted.
|
# User access is restricted.
|
||||||
# Keep verifying until access is granted
|
# Keep verifying until access is granted
|
||||||
# unless server goes offline or Kodi is shut down.
|
# unless server goes offline or Kodi is shut down.
|
||||||
while not self.userclient_thread.get_access():
|
self._access_check()
|
||||||
# Verify access with an API call
|
|
||||||
|
|
||||||
if window('emby_online') != "true":
|
|
||||||
# Server went offline
|
|
||||||
break
|
|
||||||
|
|
||||||
if self.monitor.waitForAbort(5):
|
|
||||||
# Abort was requested while waiting. We should exit
|
|
||||||
break
|
|
||||||
else:
|
else:
|
||||||
# Wait until Emby server is online
|
# Wait until Emby server is online
|
||||||
# or Kodi is shut down.
|
# or Kodi is shut down.
|
||||||
|
@ -208,18 +144,44 @@ class Service(object):
|
||||||
break
|
break
|
||||||
|
|
||||||
##### Emby thread is terminating. #####
|
##### Emby thread is terminating. #####
|
||||||
self._shutdown()
|
self.shutdown()
|
||||||
|
|
||||||
|
def _startup(self):
|
||||||
|
# Start up events
|
||||||
|
self.warn_auth = True
|
||||||
|
|
||||||
|
if settings('connectMsg') == "true":
|
||||||
|
# Get additional users
|
||||||
|
add_users = ", ".join(settings('additionalUsers').split(','))
|
||||||
|
|
||||||
|
dialog(type_="notification",
|
||||||
|
heading="{emby}",
|
||||||
|
message=("%s %s%s!"
|
||||||
|
% (lang(33000), self.userclient_thread.get_username().decode('utf-8'),
|
||||||
|
add_users.decode('utf-8'))),
|
||||||
|
icon="{emby}",
|
||||||
|
time=2000,
|
||||||
|
sound=False)
|
||||||
|
|
||||||
|
# Start the Websocket Client
|
||||||
|
self.websocket_running = True
|
||||||
|
self.websocket_thread.start()
|
||||||
|
# Start the syncing thread
|
||||||
|
self.library_running = True
|
||||||
|
self.library_thread.start()
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
def _server_online_check(self):
|
def _server_online_check(self):
|
||||||
# Set emby_online true/false property
|
# Set emby_online true/false property
|
||||||
user = self.userclient_thread
|
user_client = self.userclient_thread
|
||||||
while not self.monitor.abortRequested():
|
while not self.monitor.abortRequested():
|
||||||
|
|
||||||
if user.get_server() is None:
|
if user_client.get_server() is None:
|
||||||
# No server info set in add-on settings
|
# No server info set in add-on settings
|
||||||
pass
|
pass
|
||||||
|
|
||||||
elif not user.verify_server():
|
elif not user_client.verify_server():
|
||||||
# Server is offline.
|
# Server is offline.
|
||||||
# Alert the user and suppress future warning
|
# Alert the user and suppress future warning
|
||||||
if self.server_online:
|
if self.server_online:
|
||||||
|
@ -270,7 +232,7 @@ class Service(object):
|
||||||
# Start the userclient thread
|
# Start the userclient thread
|
||||||
if not self.userclient_running:
|
if not self.userclient_running:
|
||||||
self.userclient_running = True
|
self.userclient_running = True
|
||||||
user.start()
|
user_client.start()
|
||||||
|
|
||||||
break
|
break
|
||||||
|
|
||||||
|
@ -278,7 +240,49 @@ class Service(object):
|
||||||
# Abort was requested while waiting.
|
# Abort was requested while waiting.
|
||||||
break
|
break
|
||||||
|
|
||||||
def _shutdown(self):
|
def _access_check(self):
|
||||||
|
# Keep verifying until access is granted
|
||||||
|
# unless server goes offline or Kodi is shut down.
|
||||||
|
while not self.userclient_thread.get_access():
|
||||||
|
|
||||||
|
if window('emby_online') != "true":
|
||||||
|
# Server went offline
|
||||||
|
break
|
||||||
|
|
||||||
|
if self.monitor.waitForAbort(5):
|
||||||
|
# Abort was requested while waiting. We should exit
|
||||||
|
break
|
||||||
|
|
||||||
|
def _report_progress(self):
|
||||||
|
# Update and report playback progress
|
||||||
|
kodi_player = self.kodi_player
|
||||||
|
try:
|
||||||
|
play_time = kodi_player.getTime()
|
||||||
|
filename = kodi_player.currentFile
|
||||||
|
|
||||||
|
# Update positionticks
|
||||||
|
if filename in kodi_player.played_info:
|
||||||
|
kodi_player.played_info[filename]['currentPosition'] = play_time
|
||||||
|
|
||||||
|
difference = datetime.today() - self.last_progress
|
||||||
|
difference_seconds = difference.seconds
|
||||||
|
|
||||||
|
# Report progress to Emby server
|
||||||
|
if difference_seconds > 3:
|
||||||
|
kodi_player.reportPlayback()
|
||||||
|
self.last_progress = datetime.today()
|
||||||
|
|
||||||
|
elif window('emby_command') == "true":
|
||||||
|
# Received a remote control command that
|
||||||
|
# requires updating immediately
|
||||||
|
window('emby_command', clear=True)
|
||||||
|
kodi_player.reportPlayback()
|
||||||
|
self.last_progress = datetime.today()
|
||||||
|
|
||||||
|
except Exception as error:
|
||||||
|
log.exception(error)
|
||||||
|
|
||||||
|
def shutdown(self):
|
||||||
|
|
||||||
if self.userclient_running:
|
if self.userclient_running:
|
||||||
self.userclient_thread.stop_client()
|
self.userclient_thread.stop_client()
|
||||||
|
|
|
@ -26,18 +26,21 @@ from utils import settings
|
||||||
|
|
||||||
loghandler.config()
|
loghandler.config()
|
||||||
log = logging.getLogger("EMBY.service")
|
log = logging.getLogger("EMBY.service")
|
||||||
DELAY = settings('startupDelay') or 0
|
DELAY = int(settings('startupDelay') or 0)
|
||||||
|
|
||||||
#################################################################################################
|
#################################################################################################
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|
||||||
log.warn("Delaying emby startup by: %s sec...", DELAY)
|
log.warn("Delaying emby startup by: %s sec...", DELAY)
|
||||||
|
service = Service()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if int(DELAY) and xbmc.Monitor().waitForAbort(int(DELAY)):
|
if DELAY and xbmc.Monitor().waitForAbort(DELAY):
|
||||||
raise RuntimeError("Abort event while waiting to start Emby for kodi")
|
raise RuntimeError("Abort event while waiting to start Emby for kodi")
|
||||||
# Start the service
|
# Start the service
|
||||||
Service().service_entry_point()
|
service.service_entry_point()
|
||||||
except Exception as error:
|
except Exception as error:
|
||||||
log.exception(error)
|
log.exception(error)
|
||||||
|
log.info("Forcing shutdown")
|
||||||
|
service.shutdown()
|
||||||
|
|
Loading…
Reference in a new issue