removed plextv / pms, added TODO's for reimplementing Jellyfin

This commit is contained in:
2021-02-05 21:01:43 +01:00
parent af3c826f7d
commit 38f0a44fa0
16 changed files with 733 additions and 4835 deletions

View File

@@ -50,10 +50,7 @@
<h3 style="line-height: 50px;">Welcome!</h3> <h3 style="line-height: 50px;">Welcome!</h3>
<div class="wizard-input-section"> <div class="wizard-input-section">
<p class="welcome-message"> <p class="welcome-message">
Thanks for taking the time to try out Tautulli. Hope you find it useful. Thanks for taking the time to try out JellyPy. Hope you find it useful.
</p>
<p class="welcome-message">
Tautulli requires a permanent internet connection to ensure a reliable experience.
</p> </p>
<p class="welcome-message"> <p class="welcome-message">
This wizard will help you get set up, to continue press Next. This wizard will help you get set up, to continue press Next.
@@ -65,11 +62,11 @@
<h3>Authentication</h3> <h3>Authentication</h3>
<div class="wizard-input-section"> <div class="wizard-input-section">
<p class="help-block"> <p class="help-block">
Please setup an admin username and password for Tautulli. Please setup an admin username and password for JellyPy.
</p> </p>
</div> </div>
<div class="wizard-input-section"> <div class="wizard-input-section">
<label for="http_username">HTTP Username</label> <label for="http_username">Username</label>
<div class="row"> <div class="row">
<div class="col-xs-8"> <div class="col-xs-8">
<input type="text" class="form-control auth-settings" id="http_username" name="http_username" value="" size="30"> <input type="text" class="form-control auth-settings" id="http_username" name="http_username" value="" size="30">
@@ -77,7 +74,7 @@
</div> </div>
</div> </div>
<div class="wizard-input-section"> <div class="wizard-input-section">
<label for="http_password">HTTP Password</label> <label for="http_password">Password</label>
<div class="row"> <div class="row">
<div class="col-xs-8"> <div class="col-xs-8">
<input type="password" class="form-control auth-settings" id="http_password" name="http_password" value="" size="30" autocomplete="new-password"> <input type="password" class="form-control auth-settings" id="http_password" name="http_password" value="" size="30" autocomplete="new-password">
@@ -91,26 +88,14 @@
</div> </div>
<div class="wizard-card" data-cardname="card3"> <div class="wizard-card" data-cardname="card3">
<h3>Plex Account</h3> <h3>Jellyfin</h3>
<div class="wizard-input-section"> <div class="wizard-input-section">
<p class="help-block"> <p class="help-block">
Tautulli requires a Plex.tv account. Click the button below to sign in on Plex.tv. You may need to allow popups in your browser. Select your Jellyfin Server from the dropdown menu or enter an IP address or hostname.
</p>
</div>
<input type="hidden" class="form-control" name="pms_token" id="pms_token" value="" data-validate="validatePMStoken">
<a class="btn btn-dark" id="sign-in-plex" href="#" role="button">Sign In with Plex</a>
<span style="margin-left: 10px; display: none;" id="pms-token-status"></span>
</div>
<div class="wizard-card" data-cardname="card4">
<h3>Plex Media Server</h3>
<div class="wizard-input-section">
<p class="help-block">
Select your Plex Media Server from the dropdown menu or enter an IP address or hostname.
</p> </p>
</div> </div>
<div class="wizard-input-section"> <div class="wizard-input-section">
<label for="pms_ip_selectize">Plex IP Address or Hostname</label> <label for="pms_ip_selectize">Jellyfin IP Address or Hostname</label>
<div class="row"> <div class="row">
<div class="col-xs-12"> <div class="col-xs-12">
<select class="form-control pms-settings selectize-pms-ip" id="pms_ip_selectize"> <select class="form-control pms-settings selectize-pms-ip" id="pms_ip_selectize">
@@ -130,7 +115,7 @@
</div> </div>
</div> </div>
<div class="wizard-input-section"> <div class="wizard-input-section">
<label for="pms_port">Plex Port</label> <label for="pms_port">Jellyfin Port</label>
<div class="row"> <div class="row">
<div class="col-xs-3"> <div class="col-xs-3">
<input type="text" class="form-control pms-settings" name="pms_port" id="pms_port" placeholder="32400" value="${config['pms_port']}" required> <input type="text" class="form-control pms-settings" name="pms_port" id="pms_port" placeholder="32400" value="${config['pms_port']}" required>
@@ -161,7 +146,7 @@
<span style="margin-left: 10px; display: none;" id="pms-verify-status"></span> <span style="margin-left: 10px; display: none;" id="pms-verify-status"></span>
</div> </div>
<div class="wizard-card" data-cardname="card5"> <div class="wizard-card" data-cardname="card4">
<h3>Activity Logging</h3> <h3>Activity Logging</h3>
<div class="wizard-input-section"> <div class="wizard-input-section">
<p class="help-block"> <p class="help-block">
@@ -186,7 +171,7 @@
</div> </div>
</div> </div>
<div class="wizard-card" data-cardname="card6"> <div class="wizard-card" data-cardname="card5">
<h3>Notifications</h3> <h3>Notifications</h3>
<div class="wizard-input-section"> <div class="wizard-input-section">
<p class="help-block"> <p class="help-block">
@@ -199,7 +184,7 @@
</div> </div>
</div> </div>
<div class="wizard-card" data-cardname="card7"> <div class="wizard-card" data-cardname="card6">
<h3>Database Import</h3> <h3>Database Import</h3>
<div class="wizard-input-section"> <div class="wizard-input-section">
<p class="help-block"> <p class="help-block">

View File

@@ -47,7 +47,6 @@ from jellypy import newsletters
from jellypy import newsletter_handler from jellypy import newsletter_handler
from jellypy import notification_handler from jellypy import notification_handler
from jellypy import notifiers from jellypy import notifiers
from jellypy import plextv
from jellypy import users from jellypy import users
from jellypy import versioncheck from jellypy import versioncheck
from jellypy import web_socket from jellypy import web_socket
@@ -426,8 +425,9 @@ def initialize_scheduler():
hours=backup_hours, minutes=0, seconds=0, args=(True, True)) hours=backup_hours, minutes=0, seconds=0, args=(True, True))
if WS_CONNECTED and CONFIG.PMS_IP and CONFIG.PMS_TOKEN: if WS_CONNECTED and CONFIG.PMS_IP and CONFIG.PMS_TOKEN:
schedule_job(plextv.get_server_resources, 'Refresh Plex server URLs', # TODO: Jellyfin
hours=12 * (not bool(CONFIG.PMS_URL_MANUAL)), minutes=0, seconds=0) # schedule_job(plextv.get_server_resources, 'Refresh Plex server URLs',
# hours=12 * (not bool(CONFIG.PMS_URL_MANUAL)), minutes=0, seconds=0)
schedule_job(activity_pinger.check_server_updates, 'Check for Plex updates', schedule_job(activity_pinger.check_server_updates, 'Check for Plex updates',
hours=pms_update_check_hours * bool(CONFIG.MONITOR_PMS_UPDATES), minutes=0, seconds=0) hours=pms_update_check_hours * bool(CONFIG.MONITOR_PMS_UPDATES), minutes=0, seconds=0)
@@ -448,8 +448,9 @@ def initialize_scheduler():
else: else:
# Cancel all jobs # Cancel all jobs
schedule_job(plextv.get_server_resources, 'Refresh Plex server URLs', # TODO: Jellyfin
hours=0, minutes=0, seconds=0) # schedule_job(plextv.get_server_resources, 'Refresh Plex server URLs',
# hours=0, minutes=0, seconds=0)
schedule_job(activity_pinger.check_server_updates, 'Check for Plex updates', schedule_job(activity_pinger.check_server_updates, 'Check for Plex updates',
hours=0, minutes=0, seconds=0) hours=0, minutes=0, seconds=0)
@@ -532,7 +533,9 @@ def start():
def startup_refresh(): def startup_refresh():
# Get the real PMS urls for SSL and remote access # Get the real PMS urls for SSL and remote access
if CONFIG.PMS_TOKEN and CONFIG.PMS_IP and CONFIG.PMS_PORT: if CONFIG.PMS_TOKEN and CONFIG.PMS_IP and CONFIG.PMS_PORT:
plextv.get_server_resources() pass
# TODO: Jellyfin
# plextv.get_server_resources()
# Connect server after server resource is refreshed # Connect server after server resource is refreshed
if CONFIG.FIRST_RUN_COMPLETE: if CONFIG.FIRST_RUN_COMPLETE:

View File

@@ -27,7 +27,6 @@ from jellypy import datafactory
from jellypy import helpers from jellypy import helpers
from jellypy import logger from jellypy import logger
from jellypy import notification_handler from jellypy import notification_handler
from jellypy import pmsconnect
ACTIVITY_SCHED = None ACTIVITY_SCHED = None
@@ -60,27 +59,29 @@ class ActivityHandler(object):
def get_metadata(self, skip_cache=False): def get_metadata(self, skip_cache=False):
cache_key = None if skip_cache else self.get_session_key() cache_key = None if skip_cache else self.get_session_key()
pms_connect = pmsconnect.PmsConnect() # TODO: Jellyfin
metadata = pms_connect.get_metadata_details(rating_key=self.get_rating_key(), cache_key=cache_key) # pms_connect = pmsconnect.PmsConnect()
# metadata = pms_connect.get_metadata_details(rating_key=self.get_rating_key(), cache_key=cache_key)
if metadata: #
return metadata # if metadata:
# return metadata
return None return None
def get_live_session(self, skip_cache=False): def get_live_session(self, skip_cache=False):
pms_connect = pmsconnect.PmsConnect() # TODO: Jellyfin
session_list = pms_connect.get_current_activity(skip_cache=skip_cache) # pms_connect = pmsconnect.PmsConnect()
# session_list = pms_connect.get_current_activity(skip_cache=skip_cache)
if session_list: #
for session in session_list['sessions']: # if session_list:
if int(session['session_key']) == self.get_session_key(): # for session in session_list['sessions']:
# Live sessions don't have rating keys in sessions # if int(session['session_key']) == self.get_session_key():
# Get it from the websocket data # # Live sessions don't have rating keys in sessions
if not session['rating_key']: # # Get it from the websocket data
session['rating_key'] = self.get_rating_key() # if not session['rating_key']:
session['rating_key_websocket'] = self.get_rating_key() # session['rating_key'] = self.get_rating_key()
return session # session['rating_key_websocket'] = self.get_rating_key()
# return session
return None return None
@@ -390,11 +391,12 @@ class TimelineHandler(object):
return None return None
def get_metadata(self): def get_metadata(self):
pms_connect = pmsconnect.PmsConnect() # TODO: Jellyfin
metadata = pms_connect.get_metadata_details(self.get_rating_key()) # pms_connect = pmsconnect.PmsConnect()
# metadata = pms_connect.get_metadata_details(self.get_rating_key())
if metadata: #
return metadata # if metadata:
# return metadata
return None return None
@@ -522,9 +524,11 @@ class ReachabilityHandler(object):
return False return False
def remote_access_enabled(self): def remote_access_enabled(self):
pms_connect = pmsconnect.PmsConnect() return False
pref = pms_connect.get_server_pref(pref='PublishServerOnPlexOnlineKey') # TODO: Jellyfin
return helpers.bool_true(pref) # pms_connect = pmsconnect.PmsConnect()
# pref = pms_connect.get_server_pref(pref='PublishServerOnPlexOnlineKey')
# return helpers.bool_true(pref)
def on_down(self, server_response): def on_down(self, server_response):
jellypy.NOTIFY_QUEUE.put({'notify_action': 'on_extdown', 'remote_access_info': server_response}) jellypy.NOTIFY_QUEUE.put({'notify_action': 'on_extdown', 'remote_access_info': server_response})
@@ -541,39 +545,40 @@ class ReachabilityHandler(object):
if self.is_reachable() and jellypy.PLEX_REMOTE_ACCESS_UP: if self.is_reachable() and jellypy.PLEX_REMOTE_ACCESS_UP:
return return
pms_connect = pmsconnect.PmsConnect() # TODO: Jellyfin
server_response = pms_connect.get_server_response() # pms_connect = pmsconnect.PmsConnect()
# server_response = pms_connect.get_server_response()
if server_response: #
# Waiting for port mapping # if server_response:
if server_response['mapping_state'] == 'waiting': # # Waiting for port mapping
logger.warn("Tautulli ReachabilityHandler :: Remote access waiting for port mapping.") # if server_response['mapping_state'] == 'waiting':
# logger.warn("Tautulli ReachabilityHandler :: Remote access waiting for port mapping.")
elif jellypy.PLEX_REMOTE_ACCESS_UP is not False and server_response['reason']: #
logger.warn("Tautulli ReachabilityHandler :: Remote access failed: %s" % server_response['reason']) # elif jellypy.PLEX_REMOTE_ACCESS_UP is not False and server_response['reason']:
logger.info("Tautulli ReachabilityHandler :: Plex remote access is down.") # logger.warn("Tautulli ReachabilityHandler :: Remote access failed: %s" % server_response['reason'])
# logger.info("Tautulli ReachabilityHandler :: Plex remote access is down.")
jellypy.PLEX_REMOTE_ACCESS_UP = False #
# jellypy.PLEX_REMOTE_ACCESS_UP = False
if not ACTIVITY_SCHED.get_job('on_extdown'): #
logger.debug("Tautulli ReachabilityHandler :: Schedule remote access down callback in %d seconds.", # if not ACTIVITY_SCHED.get_job('on_extdown'):
jellypy.CONFIG.NOTIFY_REMOTE_ACCESS_THRESHOLD) # logger.debug("Tautulli ReachabilityHandler :: Schedule remote access down callback in %d seconds.",
schedule_callback('on_extdown', func=self.on_down, args=[server_response], # jellypy.CONFIG.NOTIFY_REMOTE_ACCESS_THRESHOLD)
seconds=jellypy.CONFIG.NOTIFY_REMOTE_ACCESS_THRESHOLD) # schedule_callback('on_extdown', func=self.on_down, args=[server_response],
# seconds=jellypy.CONFIG.NOTIFY_REMOTE_ACCESS_THRESHOLD)
elif jellypy.PLEX_REMOTE_ACCESS_UP is False and not server_response['reason']: #
logger.info("Tautulli ReachabilityHandler :: Plex remote access is back up.") # elif jellypy.PLEX_REMOTE_ACCESS_UP is False and not server_response['reason']:
# logger.info("Tautulli ReachabilityHandler :: Plex remote access is back up.")
jellypy.PLEX_REMOTE_ACCESS_UP = True #
# jellypy.PLEX_REMOTE_ACCESS_UP = True
if ACTIVITY_SCHED.get_job('on_extdown'): #
logger.debug("Tautulli ReachabilityHandler :: Cancelling scheduled remote access down callback.") # if ACTIVITY_SCHED.get_job('on_extdown'):
schedule_callback('on_extdown', remove_job=True) # logger.debug("Tautulli ReachabilityHandler :: Cancelling scheduled remote access down callback.")
else: # schedule_callback('on_extdown', remove_job=True)
self.on_up(server_response) # else:
# self.on_up(server_response)
elif jellypy.PLEX_REMOTE_ACCESS_UP is None: #
jellypy.PLEX_REMOTE_ACCESS_UP = self.is_reachable() # elif jellypy.PLEX_REMOTE_ACCESS_UP is None:
# jellypy.PLEX_REMOTE_ACCESS_UP = self.is_reachable()
def del_keys(key): def del_keys(key):
@@ -670,41 +675,42 @@ def clear_recently_added_queue(rating_key, title):
def on_created(rating_key, **kwargs): def on_created(rating_key, **kwargs):
logger.debug("Tautulli TimelineHandler :: Library item %s added to Plex." % str(rating_key)) logger.debug("Tautulli TimelineHandler :: Library item %s added to Plex." % str(rating_key))
pms_connect = pmsconnect.PmsConnect() # TODO: Jellyfin
metadata = pms_connect.get_metadata_details(rating_key) # pms_connect = pmsconnect.PmsConnect()
# metadata = pms_connect.get_metadata_details(rating_key)
if metadata:
notify = True
# now = helpers.timestamp()
# #
# if helpers.cast_to_int(metadata['added_at']) < now - 86400: # Updated more than 24 hours ago # if metadata:
# logger.debug("Tautulli TimelineHandler :: Library item %s added more than 24 hours ago. Not notifying." # notify = True
# # now = helpers.timestamp()
# #
# # if helpers.cast_to_int(metadata['added_at']) < now - 86400: # Updated more than 24 hours ago
# # logger.debug("Tautulli TimelineHandler :: Library item %s added more than 24 hours ago. Not notifying."
# # % str(rating_key))
# # notify = False
#
# data_factory = datafactory.DataFactory()
# if 'child_keys' not in kwargs:
# if data_factory.get_recently_added_item(rating_key):
# logger.debug("Tautulli TimelineHandler :: Library item %s added already. Not notifying again."
# % str(rating_key)) # % str(rating_key))
# notify = False # notify = False
#
data_factory = datafactory.DataFactory() # if notify:
if 'child_keys' not in kwargs: # data = {'timeline_data': metadata, 'notify_action': 'on_created'}
if data_factory.get_recently_added_item(rating_key): # data.update(kwargs)
logger.debug("Tautulli TimelineHandler :: Library item %s added already. Not notifying again." # jellypy.NOTIFY_QUEUE.put(data)
% str(rating_key)) #
notify = False # all_keys = [rating_key]
# if 'child_keys' in kwargs:
if notify: # all_keys.extend(kwargs['child_keys'])
data = {'timeline_data': metadata, 'notify_action': 'on_created'} #
data.update(kwargs) # for key in all_keys:
jellypy.NOTIFY_QUEUE.put(data) # data_factory.set_recently_added_item(key)
#
all_keys = [rating_key] # logger.debug("Added %s items to the recently_added database table." % str(len(all_keys)))
if 'child_keys' in kwargs: #
all_keys.extend(kwargs['child_keys']) # else:
# logger.error("Tautulli TimelineHandler :: Unable to retrieve metadata for rating_key %s" % str(rating_key))
for key in all_keys:
data_factory.set_recently_added_item(key)
logger.debug("Added %s items to the recently_added database table." % str(len(all_keys)))
else:
logger.error("Tautulli TimelineHandler :: Unable to retrieve metadata for rating_key %s" % str(rating_key))
def delete_metadata_cache(session_key): def delete_metadata_cache(session_key):

View File

@@ -23,8 +23,6 @@ from jellypy import database
from jellypy import helpers from jellypy import helpers
from jellypy import logger from jellypy import logger
from jellypy import notification_handler from jellypy import notification_handler
from jellypy import plextv
from jellypy import pmsconnect
from jellypy import web_socket from jellypy import web_socket
monitor_lock = threading.Lock() monitor_lock = threading.Lock()
@@ -43,8 +41,10 @@ def check_active_sessions(ws_request=False):
for stream in db_streams: for stream in db_streams:
activity_handler.delete_metadata_cache(stream['session_key']) activity_handler.delete_metadata_cache(stream['session_key'])
pms_connect = pmsconnect.PmsConnect() # TODO: Jellyfin
session_list = pms_connect.get_current_activity() # pms_connect = pmsconnect.PmsConnect()
# session_list = pms_connect.get_current_activity()
session_list = None
logger.debug("Tautulli Monitor :: Checking for active streams.") logger.debug("Tautulli Monitor :: Checking for active streams.")
@@ -229,8 +229,10 @@ def connect_server(log=True, startup=False):
if log: if log:
logger.info("Tautulli Monitor :: Checking for Plex Cloud server status...") logger.info("Tautulli Monitor :: Checking for Plex Cloud server status...")
plex_tv = plextv.PlexTV() # TODO: Jellyfin
status = plex_tv.get_cloud_server_status() # plex_tv = plextv.PlexTV()
# status = plex_tv.get_cloud_server_status()
status = None
if status is True: if status is True:
logger.info("Tautulli Monitor :: Plex Cloud server is active.") logger.info("Tautulli Monitor :: Plex Cloud server is active.")
@@ -261,16 +263,17 @@ def check_server_updates():
with monitor_lock: with monitor_lock:
logger.info("Tautulli Monitor :: Checking for PMS updates...") logger.info("Tautulli Monitor :: Checking for PMS updates...")
plex_tv = plextv.PlexTV() # TODO: Jellyfin
download_info = plex_tv.get_plex_downloads() # plex_tv = plextv.PlexTV()
# download_info = plex_tv.get_plex_downloads()
if download_info: #
logger.info("Tautulli Monitor :: Current PMS version: %s", jellypy.CONFIG.PMS_VERSION) # if download_info:
# logger.info("Tautulli Monitor :: Current PMS version: %s", jellypy.CONFIG.PMS_VERSION)
if download_info['update_available']: #
logger.info("Tautulli Monitor :: PMS update available version: %s", download_info['version']) # if download_info['update_available']:
# logger.info("Tautulli Monitor :: PMS update available version: %s", download_info['version'])
jellypy.NOTIFY_QUEUE.put({'notify_action': 'on_pmsupdate', 'pms_download_info': download_info}) #
# jellypy.NOTIFY_QUEUE.put({'notify_action': 'on_pmsupdate', 'pms_download_info': download_info})
else: #
logger.info("Tautulli Monitor :: No PMS update available.") # else:
# logger.info("Tautulli Monitor :: No PMS update available.")

View File

@@ -22,7 +22,6 @@ from jellypy import database
from jellypy import helpers from jellypy import helpers
from jellypy import libraries from jellypy import libraries
from jellypy import logger from jellypy import logger
from jellypy import pmsconnect
from jellypy import users from jellypy import users
@@ -260,19 +259,20 @@ class ActivityProcessor(object):
if not is_import: if not is_import:
logger.debug( logger.debug(
"Tautulli ActivityProcessor :: Fetching metadata for item ratingKey %s" % session['rating_key']) "Tautulli ActivityProcessor :: Fetching metadata for item ratingKey %s" % session['rating_key'])
pms_connect = pmsconnect.PmsConnect() # TODO: Jellyfin
if session['live']: # pms_connect = pmsconnect.PmsConnect()
metadata = pms_connect.get_metadata_details(rating_key=str(session['rating_key']), # if session['live']:
cache_key=session['session_key'], # metadata = pms_connect.get_metadata_details(rating_key=str(session['rating_key']),
return_cache=True) # cache_key=session['session_key'],
else: # return_cache=True)
metadata = pms_connect.get_metadata_details(rating_key=str(session['rating_key'])) # else:
if not metadata: # metadata = pms_connect.get_metadata_details(rating_key=str(session['rating_key']))
return False # if not metadata:
else: # return False
media_info = {} # else:
if 'media_info' in metadata and len(metadata['media_info']) > 0: # media_info = {}
media_info = metadata['media_info'][0] # if 'media_info' in metadata and len(metadata['media_info']) > 0:
# media_info = metadata['media_info'][0]
else: else:
metadata = import_metadata metadata = import_metadata
## TODO: Fix media info from imports. Temporary media info from import session. ## TODO: Fix media info from imports. Temporary media info from import session.

View File

@@ -40,7 +40,6 @@ from jellypy import notification_handler
from jellypy import notifiers from jellypy import notifiers
from jellypy import newsletter_handler from jellypy import newsletter_handler
from jellypy import newsletters from jellypy import newsletters
from jellypy import plextv
from jellypy import users from jellypy import users
from jellypy.password import check_hash from jellypy.password import check_hash
@@ -451,11 +450,13 @@ class API2(object):
mobile_app.set_temp_device_token(True) mobile_app.set_temp_device_token(True)
plex_server = plextv.get_server_resources(return_info=True) # TODO: Jellyfin
# plex_server = plextv.get_server_resources(return_info=True)
tautulli = jellypy.get_tautulli_info() tautulli = jellypy.get_tautulli_info()
data = {"server_id": jellypy.CONFIG.PMS_UUID} data = {"server_id": jellypy.CONFIG.PMS_UUID}
data.update(plex_server) # TODO: Jellyfin
# data.update(plex_server)
data.update(tautulli) data.update(tautulli)
return data return data

View File

@@ -25,7 +25,6 @@ from jellypy import database
from jellypy import datatables from jellypy import datatables
from jellypy import helpers from jellypy import helpers
from jellypy import logger from jellypy import logger
from jellypy import pmsconnect
from jellypy import session from jellypy import session
@@ -1589,7 +1588,7 @@ class DataFactory(object):
return key_list return key_list
def update_metadata(self, old_key_list='', new_key_list='', media_type=''): def update_metadata(self, old_key_list='', new_key_list='', media_type=''):
pms_connect = pmsconnect.PmsConnect() # TODO: pms_connect = pmsconnect.PmsConnect()
monitor_db = database.MonitorDatabase() monitor_db = database.MonitorDatabase()
# function to map rating keys pairs # function to map rating keys pairs
@@ -1608,37 +1607,38 @@ class DataFactory(object):
if old_key_list and new_key_list: if old_key_list and new_key_list:
mapping = get_pairs(old_key_list, new_key_list) mapping = get_pairs(old_key_list, new_key_list)
if mapping: # TODO: Jellyfin
logger.info("Tautulli DataFactory :: Updating metadata in the database.") # if mapping:
for old_key, new_key in mapping.items(): # logger.info("Tautulli DataFactory :: Updating metadata in the database.")
metadata = pms_connect.get_metadata_details(new_key) # for old_key, new_key in mapping.items():
# metadata = pms_connect.get_metadata_details(new_key)
if metadata: #
if metadata['media_type'] == 'show' or metadata['media_type'] == 'artist': # if metadata:
# check grandparent_rating_key (2 tables) # if metadata['media_type'] == 'show' or metadata['media_type'] == 'artist':
monitor_db.action( # # check grandparent_rating_key (2 tables)
'UPDATE session_history SET grandparent_rating_key = ? WHERE grandparent_rating_key = ?', # monitor_db.action(
[new_key, old_key]) # 'UPDATE session_history SET grandparent_rating_key = ? WHERE grandparent_rating_key = ?',
monitor_db.action( # [new_key, old_key])
'UPDATE session_history_metadata SET grandparent_rating_key = ? WHERE grandparent_rating_key = ?', # monitor_db.action(
[new_key, old_key]) # 'UPDATE session_history_metadata SET grandparent_rating_key = ? WHERE grandparent_rating_key = ?',
elif metadata['media_type'] == 'season' or metadata['media_type'] == 'album': # [new_key, old_key])
# check parent_rating_key (2 tables) # elif metadata['media_type'] == 'season' or metadata['media_type'] == 'album':
monitor_db.action( # # check parent_rating_key (2 tables)
'UPDATE session_history SET parent_rating_key = ? WHERE parent_rating_key = ?', # monitor_db.action(
[new_key, old_key]) # 'UPDATE session_history SET parent_rating_key = ? WHERE parent_rating_key = ?',
monitor_db.action( # [new_key, old_key])
'UPDATE session_history_metadata SET parent_rating_key = ? WHERE parent_rating_key = ?', # monitor_db.action(
[new_key, old_key]) # 'UPDATE session_history_metadata SET parent_rating_key = ? WHERE parent_rating_key = ?',
else: # [new_key, old_key])
# check rating_key (2 tables) # else:
monitor_db.action('UPDATE session_history SET rating_key = ? WHERE rating_key = ?', # # check rating_key (2 tables)
[new_key, old_key]) # monitor_db.action('UPDATE session_history SET rating_key = ? WHERE rating_key = ?',
monitor_db.action('UPDATE session_history_media_info SET rating_key = ? WHERE rating_key = ?', # [new_key, old_key])
[new_key, old_key]) # monitor_db.action('UPDATE session_history_media_info SET rating_key = ? WHERE rating_key = ?',
# [new_key, old_key])
# update session_history_metadata table #
self.update_metadata_details(old_key, new_key, metadata) # # update session_history_metadata table
# self.update_metadata_details(old_key, new_key, metadata)
return 'Updated metadata in database.' return 'Updated metadata in database.'
else: else:
@@ -1886,23 +1886,24 @@ class DataFactory(object):
def set_recently_added_item(self, rating_key=''): def set_recently_added_item(self, rating_key=''):
monitor_db = database.MonitorDatabase() monitor_db = database.MonitorDatabase()
pms_connect = pmsconnect.PmsConnect() # TODO: Jellyfin
metadata = pms_connect.get_metadata_details(rating_key) # pms_connect = pmsconnect.PmsConnect()
# metadata = pms_connect.get_metadata_details(rating_key)
keys = {'rating_key': metadata['rating_key']} #
# keys = {'rating_key': metadata['rating_key']}
values = {'added_at': metadata['added_at'], #
'section_id': metadata['section_id'], # values = {'added_at': metadata['added_at'],
'parent_rating_key': metadata['parent_rating_key'], # 'section_id': metadata['section_id'],
'grandparent_rating_key': metadata['grandparent_rating_key'], # 'parent_rating_key': metadata['parent_rating_key'],
'media_type': metadata['media_type'], # 'grandparent_rating_key': metadata['grandparent_rating_key'],
'media_info': json.dumps(metadata['media_info']) # 'media_type': metadata['media_type'],
} # 'media_info': json.dumps(metadata['media_info'])
# }
try: #
monitor_db.upsert(table_name='recently_added', key_dict=keys, value_dict=values) # try:
except Exception as e: # monitor_db.upsert(table_name='recently_added', key_dict=keys, value_dict=values)
logger.warn("Tautulli DataFactory :: Unable to execute database query for set_recently_added_item: %s." % e) # except Exception as e:
return False # logger.warn("Tautulli DataFactory :: Unable to execute database query for set_recently_added_item: %s." % e)
# return False
return True return True

View File

@@ -25,8 +25,6 @@ from jellypy import database
from jellypy import datatables from jellypy import datatables
from jellypy import helpers from jellypy import helpers
from jellypy import logger from jellypy import logger
from jellypy import plextv
from jellypy import pmsconnect
from jellypy import session from jellypy import session
from jellypy import users from jellypy import users
from jellypy.jellyfin import Jellyfin from jellypy.jellyfin import Jellyfin
@@ -1159,7 +1157,7 @@ class Libraries(object):
monitor_db = database.MonitorDatabase() monitor_db = database.MonitorDatabase()
# Refresh the PMS_URL to make sure the server_id is updated # Refresh the PMS_URL to make sure the server_id is updated
plextv.get_server_resources() # TODO: plextv.get_server_resources()
server_id = jellypy.CONFIG.PMS_IDENTIFIER server_id = jellypy.CONFIG.PMS_IDENTIFIER

View File

@@ -32,7 +32,6 @@ from jellypy import helpers
from jellypy import libraries from jellypy import libraries
from jellypy import logger from jellypy import logger
from jellypy import newsletter_handler from jellypy import newsletter_handler
from jellypy import pmsconnect
from jellypy.notifiers import send_notification, EMAIL from jellypy.notifiers import send_notification, EMAIL
AGENT_IDS = { AGENT_IDS = {
@@ -693,7 +692,8 @@ class RecentlyAdded(Newsletter):
def _get_recently_added(self, media_type=None): def _get_recently_added(self, media_type=None):
from jellypy.notification_handler import format_group_index from jellypy.notification_handler import format_group_index
pms_connect = pmsconnect.PmsConnect() # TODO: Jellyfin
# pms_connect = pmsconnect.PmsConnect()
recently_added = [] recently_added = []
done = False done = False

View File

@@ -39,7 +39,6 @@ from jellypy import datafactory
from jellypy import logger from jellypy import logger
from jellypy import helpers from jellypy import helpers
from jellypy import notifiers from jellypy import notifiers
from jellypy import pmsconnect
from jellypy import request from jellypy import request
from jellypy.newsletter_handler import notify as notify_newsletter from jellypy.newsletter_handler import notify as notify_newsletter
@@ -164,18 +163,20 @@ def notify_conditions(notify_action=None, stream_data=None, timeline_data=None):
# return False # return False
if notify_action == 'on_concurrent': if notify_action == 'on_concurrent':
pms_connect = pmsconnect.PmsConnect() pass
result = pms_connect.get_current_activity() # TODO: Jellyfin
# pms_connect = pmsconnect.PmsConnect()
user_sessions = [] # result = pms_connect.get_current_activity()
if result: #
user_sessions = [s for s in result['sessions'] if s['user_id'] == stream_data['user_id']] # user_sessions = []
# if result:
if jellypy.CONFIG.NOTIFY_CONCURRENT_BY_IP: # user_sessions = [s for s in result['sessions'] if s['user_id'] == stream_data['user_id']]
evaluated = len( #
Counter(s['ip_address'] for s in user_sessions)) >= jellypy.CONFIG.NOTIFY_CONCURRENT_THRESHOLD # if jellypy.CONFIG.NOTIFY_CONCURRENT_BY_IP:
else: # evaluated = len(
evaluated = len(user_sessions) >= jellypy.CONFIG.NOTIFY_CONCURRENT_THRESHOLD # Counter(s['ip_address'] for s in user_sessions)) >= jellypy.CONFIG.NOTIFY_CONCURRENT_THRESHOLD
# else:
# evaluated = len(user_sessions) >= jellypy.CONFIG.NOTIFY_CONCURRENT_THRESHOLD
elif notify_action == 'on_newdevice': elif notify_action == 'on_newdevice':
data_factory = datafactory.DataFactory() data_factory = datafactory.DataFactory()
@@ -536,10 +537,11 @@ def build_media_notify_params(notify_action=None, session=None, timeline=None, m
notify_params.update(media_part_info) notify_params.update(media_part_info)
child_metadata = grandchild_metadata = [] child_metadata = grandchild_metadata = []
for key in kwargs.pop('child_keys', []): # TODO: Jellyfin
child_metadata.append(pmsconnect.PmsConnect().get_metadata_details(rating_key=key)) # for key in kwargs.pop('child_keys', []):
for key in kwargs.pop('grandchild_keys', []): # child_metadata.append(pmsconnect.PmsConnect().get_metadata_details(rating_key=key))
grandchild_metadata.append(pmsconnect.PmsConnect().get_metadata_details(rating_key=key)) # for key in kwargs.pop('grandchild_keys', []):
# grandchild_metadata.append(pmsconnect.PmsConnect().get_metadata_details(rating_key=key))
# Session values # Session values
session = session or {} session = session or {}
@@ -1097,7 +1099,8 @@ def build_server_notify_params(notify_action=None, **kwargs):
date_format = jellypy.CONFIG.DATE_FORMAT.replace('Do', '') date_format = jellypy.CONFIG.DATE_FORMAT.replace('Do', '')
time_format = jellypy.CONFIG.TIME_FORMAT.replace('Do', '') time_format = jellypy.CONFIG.TIME_FORMAT.replace('Do', '')
update_channel = pmsconnect.PmsConnect().get_server_update_channel() # TODO: Jellyfin
# update_channel = pmsconnect.PmsConnect().get_server_update_channel()
pms_download_info = defaultdict(str, kwargs.pop('pms_download_info', {})) pms_download_info = defaultdict(str, kwargs.pop('pms_download_info', {}))
plexpy_download_info = defaultdict(str, kwargs.pop('plexpy_download_info', {})) plexpy_download_info = defaultdict(str, kwargs.pop('plexpy_download_info', {}))
@@ -1146,7 +1149,8 @@ def build_server_notify_params(notify_action=None, **kwargs):
'update_url': pms_download_info['download_url'], 'update_url': pms_download_info['download_url'],
'update_release_date': arrow.get(pms_download_info['release_date']).format(date_format) 'update_release_date': arrow.get(pms_download_info['release_date']).format(date_format)
if pms_download_info['release_date'] else '', if pms_download_info['release_date'] else '',
'update_channel': 'Beta' if update_channel == 'beta' else 'Public', # TODO: Jellyfin
# 'update_channel': 'Beta' if update_channel == 'beta' else 'Public',
'update_platform': pms_download_info['platform'], 'update_platform': pms_download_info['platform'],
'update_distro': pms_download_info['distro'], 'update_distro': pms_download_info['distro'],
'update_distro_build': pms_download_info['build'], 'update_distro_build': pms_download_info['build'],
@@ -1410,32 +1414,34 @@ def get_img_info(img=None, rating_key=None, title='', width=1000, height=1500,
img_info = database_img_info[0] img_info = database_img_info[0]
elif not database_img_info and img: elif not database_img_info and img:
pms_connect = pmsconnect.PmsConnect() pass
result = pms_connect.get_image(refresh=True, **image_info) # TODO: Jellyfin
# pms_connect = pmsconnect.PmsConnect()
if result and result[0]: # result = pms_connect.get_image(refresh=True, **image_info)
img_url = delete_hash = '' #
# if result and result[0]:
if service == 'imgur': # img_url = delete_hash = ''
img_url, delete_hash = helpers.upload_to_imgur(img_data=result[0], #
img_title=title, # if service == 'imgur':
rating_key=rating_key, # img_url, delete_hash = helpers.upload_to_imgur(img_data=result[0],
fallback=fallback) # img_title=title,
elif service == 'cloudinary': # rating_key=rating_key,
img_url = helpers.upload_to_cloudinary(img_data=result[0], # fallback=fallback)
img_title=title, # elif service == 'cloudinary':
rating_key=rating_key, # img_url = helpers.upload_to_cloudinary(img_data=result[0],
fallback=fallback) # img_title=title,
# rating_key=rating_key,
if img_url: # fallback=fallback)
img_hash = set_hash_image_info(**image_info) #
data_factory.set_img_info(img_hash=img_hash, # if img_url:
img_title=title, # img_hash = set_hash_image_info(**image_info)
img_url=img_url, # data_factory.set_img_info(img_hash=img_hash,
delete_hash=delete_hash, # img_title=title,
service=service) # img_url=img_url,
# delete_hash=delete_hash,
img_info = {'img_title': title, 'img_url': img_url} # service=service)
#
# img_info = {'img_title': title, 'img_url': img_url}
if img_info['img_url'] and service == 'cloudinary': if img_info['img_url'] and service == 'cloudinary':
# Transform image using Cloudinary # Transform image using Cloudinary

View File

@@ -61,7 +61,6 @@ from jellypy import database
from jellypy import helpers from jellypy import helpers
from jellypy import logger from jellypy import logger
from jellypy import mobile_app from jellypy import mobile_app
from jellypy import pmsconnect
from jellypy import request from jellypy import request
from jellypy import users from jellypy import users
@@ -1517,29 +1516,30 @@ class GROUPME(Notifier):
if self.config['incl_poster'] and kwargs.get('parameters'): if self.config['incl_poster'] and kwargs.get('parameters'):
pretty_metadata = PrettyMetadata(kwargs.get('parameters')) pretty_metadata = PrettyMetadata(kwargs.get('parameters'))
# Retrieve the poster from Plex # TODO: Jellyfin
result = pmsconnect.PmsConnect().get_image(img=pretty_metadata.parameters.get('poster_thumb', '')) # # Retrieve the poster from Plex
if result and result[0]: # result = pmsconnect.PmsConnect().get_image(img=pretty_metadata.parameters.get('poster_thumb', ''))
poster_content = result[0] # if result and result[0]:
else: # poster_content = result[0]
poster_content = '' # else:
logger.error("Tautulli Notifiers :: Unable to retrieve image for {name}.".format(name=self.NAME)) # poster_content = ''
# logger.error("Tautulli Notifiers :: Unable to retrieve image for {name}.".format(name=self.NAME))
if poster_content: #
headers = {'X-Access-Token': self.config['access_token'], # if poster_content:
'Content-Type': 'image/png'} # headers = {'X-Access-Token': self.config['access_token'],
# 'Content-Type': 'image/png'}
r = requests.post('https://image.groupme.com/pictures', headers=headers, data=poster_content) #
# r = requests.post('https://image.groupme.com/pictures', headers=headers, data=poster_content)
if r.status_code == 200: #
logger.info("Tautulli Notifiers :: {name} poster sent.".format(name=self.NAME)) # if r.status_code == 200:
r_content = r.json() # logger.info("Tautulli Notifiers :: {name} poster sent.".format(name=self.NAME))
data['attachments'] = [{'type': 'image', # r_content = r.json()
'url': r_content['payload']['picture_url']}] # data['attachments'] = [{'type': 'image',
else: # 'url': r_content['payload']['picture_url']}]
logger.error("Tautulli Notifiers :: {name} poster failed: " # else:
"[{r.status_code}] {r.reason}".format(name=self.NAME, r=r)) # logger.error("Tautulli Notifiers :: {name} poster failed: "
logger.debug("Tautulli Notifiers :: Request response: {}".format(request.server_message(r, True))) # "[{r.status_code}] {r.reason}".format(name=self.NAME, r=r))
# logger.debug("Tautulli Notifiers :: Request response: {}".format(request.server_message(r, True)))
return self.make_request('https://api.groupme.com/v3/bots/post', json=data) return self.make_request('https://api.groupme.com/v3/bots/post', json=data)

View File

@@ -1,978 +0,0 @@
# -*- coding: utf-8 -*-
# This file is part of Tautulli.
#
# Tautulli is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Tautulli is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Tautulli. If not, see <http://www.gnu.org/licenses/>.
import json
import jellypy
from jellypy import common
from jellypy import helpers
from jellypy import http_handler
from jellypy import logger
from jellypy import users
from jellypy import pmsconnect
from jellypy import session
def get_server_resources(return_presence=False, return_server=False, return_info=False, **kwargs):
if not return_presence and not return_info:
logger.info("Tautulli PlexTV :: Requesting resources for server...")
server = {'pms_name': jellypy.CONFIG.PMS_NAME,
'pms_version': jellypy.CONFIG.PMS_VERSION,
'pms_platform': jellypy.CONFIG.PMS_PLATFORM,
'pms_ip': jellypy.CONFIG.PMS_IP,
'pms_port': jellypy.CONFIG.PMS_PORT,
'pms_ssl': jellypy.CONFIG.PMS_SSL,
'pms_is_remote': jellypy.CONFIG.PMS_IS_REMOTE,
'pms_is_cloud': jellypy.CONFIG.PMS_IS_CLOUD,
'pms_url': jellypy.CONFIG.PMS_URL,
'pms_url_manual': jellypy.CONFIG.PMS_URL_MANUAL,
'pms_identifier': jellypy.CONFIG.PMS_IDENTIFIER,
'pms_plexpass': jellypy.CONFIG.PMS_PLEXPASS
}
if return_info:
return server
if kwargs:
server.update(kwargs)
for k in ['pms_ssl', 'pms_is_remote', 'pms_is_cloud', 'pms_url_manual']:
server[k] = int(server[k])
if server['pms_url_manual'] and server['pms_ssl'] or server['pms_is_cloud']:
scheme = 'https'
else:
scheme = 'http'
fallback_url = '{scheme}://{hostname}:{port}'.format(scheme=scheme,
hostname=server['pms_ip'],
port=server['pms_port'])
plex_tv = PlexTV()
result = plex_tv.get_server_connections(pms_identifier=server['pms_identifier'],
pms_ip=server['pms_ip'],
pms_port=server['pms_port'],
include_https=server['pms_ssl'])
if result:
connections = result.pop('connections', [])
server.update(result)
presence = server.pop('pms_presence', 0)
else:
connections = []
presence = 0
if return_presence:
return presence
plexpass = plex_tv.get_plexpass_status()
server['pms_plexpass'] = int(plexpass)
# Only need to retrieve PMS_URL if using SSL
if not server['pms_url_manual'] and server['pms_ssl']:
if connections:
if server['pms_is_remote']:
# Get all remote connections
conns = [c for c in connections if
c['local'] == '0' and ('plex.direct' in c['uri'] or 'plex.service' in c['uri'])]
else:
# Get all local connections
conns = [c for c in connections if
c['local'] == '1' and ('plex.direct' in c['uri'] or 'plex.service' in c['uri'])]
if conns:
# Get connection with matching address, otherwise return first connection
conn = next((c for c in conns if c['address'] == server['pms_ip']
and c['port'] == str(server['pms_port'])), conns[0])
server['pms_url'] = conn['uri']
logger.info("Tautulli PlexTV :: Server URL retrieved.")
# get_server_urls() failed or PMS_URL not found, fallback url doesn't use SSL
if not server['pms_url']:
server['pms_url'] = fallback_url
logger.warn("Tautulli PlexTV :: Unable to retrieve server URLs. Using user-defined value without SSL.")
# Not using SSL, remote has no effect
else:
server['pms_url'] = fallback_url
logger.info("Tautulli PlexTV :: Using user-defined URL.")
if return_server:
return server
logger.info("Tautulli PlexTV :: Selected server: %s (%s) (%s - Version %s)",
server['pms_name'], server['pms_url'], server['pms_platform'], server['pms_version'])
jellypy.CONFIG.process_kwargs(server)
jellypy.CONFIG.write()
class PlexTV(object):
"""
Plex.tv authentication
"""
def __init__(self, username=None, password=None, token=None, headers=None):
self.username = username
self.password = password
self.token = token
self.urls = 'https://plex.tv'
self.timeout = jellypy.CONFIG.PMS_TIMEOUT
self.ssl_verify = jellypy.CONFIG.VERIFY_SSL_CERT
if self.username is None and self.password is None:
if not self.token:
# Check if we should use the admin token, or the guest server token
if session.get_session_user_id():
user_data = users.Users()
user_tokens = user_data.get_tokens(user_id=session.get_session_user_id())
self.token = user_tokens['server_token']
else:
self.token = jellypy.CONFIG.PMS_TOKEN
if not self.token:
logger.error("Tautulli PlexTV :: PlexTV called, but no token provided.")
return
self.request_handler = http_handler.HTTPHandler(urls=self.urls,
token=self.token,
timeout=self.timeout,
ssl_verify=self.ssl_verify,
headers=headers)
def get_plex_auth(self, output_format='raw'):
uri = '/api/v2/users/signin'
headers = {'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
'Accept': 'application/xml'}
data = {'login': self.username,
'password': self.password,
'rememberMe': True}
request = self.request_handler.make_request(uri=uri,
request_type='POST',
headers=headers,
data=data,
output_format=output_format,
no_token=True,
encode_multipart=False)
return request
def get_token(self):
plextv_response = self.get_plex_auth(output_format='xml')
if plextv_response:
try:
xml_head = plextv_response.getElementsByTagName('user')
if xml_head:
user = {'auth_token': xml_head[0].getAttribute('authToken'),
'user_id': xml_head[0].getAttribute('id')
}
else:
logger.warn("Tautulli PlexTV :: Could not get Plex authentication token.")
except Exception as e:
logger.warn("Tautulli PlexTV :: Unable to parse XML for get_token: %s." % e)
return None
return user
else:
return None
def get_plexpy_pms_token(self, force=False):
if force:
logger.debug("Tautulli PlexTV :: Forcing refresh of Plex.tv token.")
devices_list = self.get_devices_list()
device_id = next((d for d in devices_list if d['device_identifier'] == jellypy.CONFIG.PMS_UUID), {}).get(
'device_id', None)
if device_id:
logger.debug("Tautulli PlexTV :: Removing Tautulli from Plex.tv devices.")
try:
self.delete_plextv_device(device_id=device_id)
except:
logger.error("Tautulli PlexTV :: Failed to remove Tautulli from Plex.tv devices.")
return None
else:
logger.warn("Tautulli PlexTV :: No existing Tautulli device found.")
logger.info("Tautulli PlexTV :: Fetching a new Plex.tv token for Tautulli.")
user = self.get_token()
if user:
token = user['auth_token']
jellypy.CONFIG.__setattr__('PMS_TOKEN', token)
jellypy.CONFIG.write()
logger.info("Tautulli PlexTV :: Updated Plex.tv token for Tautulli.")
return token
def get_server_token(self):
servers = self.get_plextv_resources(output_format='xml')
server_token = ''
try:
xml_head = servers.getElementsByTagName('Device')
except Exception as e:
logger.warn("Tautulli PlexTV :: Unable to parse XML for get_server_token: %s." % e)
return None
for a in xml_head:
if helpers.get_xml_attr(a, 'clientIdentifier') == jellypy.CONFIG.PMS_IDENTIFIER \
and 'server' in helpers.get_xml_attr(a, 'provides'):
server_token = helpers.get_xml_attr(a, 'accessToken')
break
return server_token
def get_plextv_pin(self, pin='', output_format=''):
if pin:
uri = '/api/v2/pins/' + pin
request = self.request_handler.make_request(uri=uri,
request_type='GET',
output_format=output_format,
no_token=True)
else:
uri = '/api/v2/pins?strong=true'
request = self.request_handler.make_request(uri=uri,
request_type='POST',
output_format=output_format,
no_token=True)
return request
def get_pin(self, pin=''):
plextv_response = self.get_plextv_pin(pin=pin,
output_format='xml')
if plextv_response:
try:
xml_head = plextv_response.getElementsByTagName('pin')
if xml_head:
pin = {'id': xml_head[0].getAttribute('id'),
'code': xml_head[0].getAttribute('code'),
'token': xml_head[0].getAttribute('authToken')
}
return pin
else:
logger.warn("Tautulli PlexTV :: Could not get Plex authentication pin.")
return None
except Exception as e:
logger.warn("Tautulli PlexTV :: Unable to parse XML for get_pin: %s." % e)
return None
else:
return None
def get_plextv_user_data(self):
plextv_response = self.get_plex_auth(output_format='dict')
if plextv_response:
return plextv_response
else:
return []
def get_plextv_friends(self, output_format=''):
uri = '/api/users'
request = self.request_handler.make_request(uri=uri,
request_type='GET',
output_format=output_format)
return request
def get_plextv_user_details(self, output_format=''):
uri = '/users/account'
request = self.request_handler.make_request(uri=uri,
request_type='GET',
output_format=output_format)
return request
def get_plextv_devices_list(self, output_format=''):
uri = '/devices.xml'
request = self.request_handler.make_request(uri=uri,
request_type='GET',
output_format=output_format)
return request
def get_plextv_server_list(self, output_format=''):
uri = '/pms/servers.xml'
request = self.request_handler.make_request(uri=uri,
request_type='GET',
output_format=output_format)
return request
def get_plextv_shared_servers(self, machine_id='', output_format=''):
uri = '/api/servers/%s/shared_servers' % machine_id
request = self.request_handler.make_request(uri=uri,
request_type='GET',
output_format=output_format)
return request
def get_plextv_sync_lists(self, machine_id='', output_format=''):
uri = '/servers/%s/sync_lists' % machine_id
request = self.request_handler.make_request(uri=uri,
request_type='GET',
output_format=output_format)
return request
def get_plextv_resources(self, include_https=False, output_format=''):
if include_https:
uri = '/api/resources?includeHttps=1'
else:
uri = '/api/resources'
request = self.request_handler.make_request(uri=uri,
request_type='GET',
output_format=output_format)
return request
def get_plextv_downloads(self, plexpass=False, output_format=''):
if plexpass:
uri = '/api/downloads/5.json?channel=plexpass'
else:
uri = '/api/downloads/1.json'
request = self.request_handler.make_request(uri=uri,
request_type='GET',
output_format=output_format)
return request
def delete_plextv_device(self, device_id='', output_format=''):
uri = '/devices/%s.xml' % device_id
request = self.request_handler.make_request(uri=uri,
request_type='DELETE',
output_format=output_format)
return request
def delete_plextv_device_sync_lists(self, client_id='', output_format=''):
uri = '/devices/%s/sync_items' % client_id
request = self.request_handler.make_request(uri=uri,
request_type='GET',
output_format=output_format)
return request
def delete_plextv_sync(self, client_id='', sync_id='', output_format=''):
uri = '/devices/%s/sync_items/%s' % (client_id, sync_id)
request = self.request_handler.make_request(uri=uri,
request_type='DELETE',
output_format=output_format)
return request
def cloud_server_status(self, output_format=''):
uri = '/api/v2/cloud_server'
request = self.request_handler.make_request(uri=uri,
request_type='GET',
output_format=output_format)
return request
def get_plextv_geoip(self, ip_address='', output_format=''):
uri = '/api/v2/geoip?ip_address=%s' % ip_address
request = self.request_handler.make_request(uri=uri,
request_type='GET',
output_format=output_format)
return request
def get_full_users_list(self):
own_account = self.get_plextv_user_details(output_format='xml')
friends_list = self.get_plextv_friends(output_format='xml')
shared_servers = self.get_plextv_shared_servers(machine_id=jellypy.CONFIG.PMS_IDENTIFIER,
output_format='xml')
users_list = []
try:
xml_head = own_account.getElementsByTagName('user')
except Exception as e:
logger.warn("Tautulli PlexTV :: Unable to parse own account XML for get_full_users_list: %s." % e)
return []
for a in xml_head:
own_details = {"user_id": helpers.get_xml_attr(a, 'id'),
"username": helpers.get_xml_attr(a, 'username'),
"thumb": helpers.get_xml_attr(a, 'thumb'),
"email": helpers.get_xml_attr(a, 'email'),
"is_active": 1,
"is_admin": 1,
"is_home_user": helpers.get_xml_attr(a, 'home'),
"is_allow_sync": 1,
"is_restricted": helpers.get_xml_attr(a, 'restricted'),
"filter_all": helpers.get_xml_attr(a, 'filterAll'),
"filter_movies": helpers.get_xml_attr(a, 'filterMovies'),
"filter_tv": helpers.get_xml_attr(a, 'filterTelevision'),
"filter_music": helpers.get_xml_attr(a, 'filterMusic'),
"filter_photos": helpers.get_xml_attr(a, 'filterPhotos'),
"user_token": helpers.get_xml_attr(a, 'authToken'),
"server_token": helpers.get_xml_attr(a, 'authToken'),
"shared_libraries": None,
}
users_list.append(own_details)
try:
xml_head = friends_list.getElementsByTagName('User')
except Exception as e:
logger.warn("Tautulli PlexTV :: Unable to parse friends list XML for get_full_users_list: %s." % e)
return []
for a in xml_head:
friend = {"user_id": helpers.get_xml_attr(a, 'id'),
"username": helpers.get_xml_attr(a, 'title'),
"thumb": helpers.get_xml_attr(a, 'thumb'),
"email": helpers.get_xml_attr(a, 'email'),
"is_active": 1,
"is_admin": 0,
"is_home_user": helpers.get_xml_attr(a, 'home'),
"is_allow_sync": helpers.get_xml_attr(a, 'allowSync'),
"is_restricted": helpers.get_xml_attr(a, 'restricted'),
"filter_all": helpers.get_xml_attr(a, 'filterAll'),
"filter_movies": helpers.get_xml_attr(a, 'filterMovies'),
"filter_tv": helpers.get_xml_attr(a, 'filterTelevision'),
"filter_music": helpers.get_xml_attr(a, 'filterMusic'),
"filter_photos": helpers.get_xml_attr(a, 'filterPhotos')
}
users_list.append(friend)
try:
xml_head = shared_servers.getElementsByTagName('SharedServer')
except Exception as e:
logger.warn("Tautulli PlexTV :: Unable to parse shared server list XML for get_full_users_list: %s." % e)
return []
user_map = {}
for a in xml_head:
user_id = helpers.get_xml_attr(a, 'userID')
server_token = helpers.get_xml_attr(a, 'accessToken')
sections = a.getElementsByTagName('Section')
shared_libraries = [helpers.get_xml_attr(s, 'key')
for s in sections if helpers.get_xml_attr(s, 'shared') == '1']
user_map[user_id] = {'server_token': server_token,
'shared_libraries': shared_libraries}
for u in users_list:
d = user_map.get(u['user_id'], {})
u.update(d)
return users_list
def get_synced_items(self, machine_id=None, client_id_filter=None, user_id_filter=None,
rating_key_filter=None, sync_id_filter=None):
if not machine_id:
machine_id = jellypy.CONFIG.PMS_IDENTIFIER
if isinstance(rating_key_filter, list):
rating_key_filter = [str(k) for k in rating_key_filter]
elif rating_key_filter:
rating_key_filter = [str(rating_key_filter)]
if isinstance(user_id_filter, list):
user_id_filter = [str(k) for k in user_id_filter]
elif user_id_filter:
user_id_filter = [str(user_id_filter)]
sync_list = self.get_plextv_sync_lists(machine_id, output_format='xml')
user_data = users.Users()
synced_items = []
try:
xml_head = sync_list.getElementsByTagName('SyncList')
except Exception as e:
logger.warn("Tautulli PlexTV :: Unable to parse XML for get_synced_items: %s." % e)
return {}
for a in xml_head:
client_id = helpers.get_xml_attr(a, 'clientIdentifier')
# Filter by client_id
if client_id_filter and str(client_id_filter) != client_id:
continue
sync_list_id = helpers.get_xml_attr(a, 'id')
sync_device = a.getElementsByTagName('Device')
for device in sync_device:
device_user_id = helpers.get_xml_attr(device, 'userID')
try:
device_username = user_data.get_details(user_id=device_user_id)['username']
device_friendly_name = user_data.get_details(user_id=device_user_id)['friendly_name']
except:
device_username = ''
device_friendly_name = ''
device_name = helpers.get_xml_attr(device, 'name')
device_product = helpers.get_xml_attr(device, 'product')
device_product_version = helpers.get_xml_attr(device, 'productVersion')
device_platform = helpers.get_xml_attr(device, 'platform')
device_platform_version = helpers.get_xml_attr(device, 'platformVersion')
device_type = helpers.get_xml_attr(device, 'device')
device_model = helpers.get_xml_attr(device, 'model')
device_last_seen = helpers.get_xml_attr(device, 'lastSeenAt')
# Filter by user_id
if user_id_filter and device_user_id not in user_id_filter:
continue
for synced in a.getElementsByTagName('SyncItems'):
sync_item = synced.getElementsByTagName('SyncItem')
for item in sync_item:
for location in item.getElementsByTagName('Location'):
clean_uri = helpers.get_xml_attr(location, 'uri').split('%2F')
rating_key = next((clean_uri[(idx + 1) % len(clean_uri)]
for idx, item in enumerate(clean_uri) if item == 'metadata'), None)
# Filter by rating_key
if rating_key_filter and rating_key not in rating_key_filter:
continue
sync_id = helpers.get_xml_attr(item, 'id')
# Filter by sync_id
if sync_id_filter and str(sync_id_filter) != sync_id:
continue
sync_version = helpers.get_xml_attr(item, 'version')
sync_root_title = helpers.get_xml_attr(item, 'rootTitle')
sync_title = helpers.get_xml_attr(item, 'title')
sync_metadata_type = helpers.get_xml_attr(item, 'metadataType')
sync_content_type = helpers.get_xml_attr(item, 'contentType')
for status in item.getElementsByTagName('Status'):
status_failure_code = helpers.get_xml_attr(status, 'failureCode')
status_failure = helpers.get_xml_attr(status, 'failure')
status_state = helpers.get_xml_attr(status, 'state')
status_item_count = helpers.get_xml_attr(status, 'itemsCount')
status_item_complete_count = helpers.get_xml_attr(status, 'itemsCompleteCount')
status_item_downloaded_count = helpers.get_xml_attr(status, 'itemsDownloadedCount')
status_item_ready_count = helpers.get_xml_attr(status, 'itemsReadyCount')
status_item_successful_count = helpers.get_xml_attr(status, 'itemsSuccessfulCount')
status_total_size = helpers.get_xml_attr(status, 'totalSize')
status_item_download_percent_complete = helpers.get_percent(
status_item_downloaded_count, status_item_count)
for settings in item.getElementsByTagName('MediaSettings'):
settings_video_bitrate = helpers.get_xml_attr(settings, 'maxVideoBitrate')
settings_video_quality = helpers.get_xml_attr(settings, 'videoQuality')
settings_video_resolution = helpers.get_xml_attr(settings, 'videoResolution')
settings_audio_boost = helpers.get_xml_attr(settings, 'audioBoost')
settings_audio_bitrate = helpers.get_xml_attr(settings, 'musicBitrate')
settings_photo_quality = helpers.get_xml_attr(settings, 'photoQuality')
settings_photo_resolution = helpers.get_xml_attr(settings, 'photoResolution')
sync_details = {"device_name": device_name,
"platform": device_platform,
"user_id": device_user_id,
"user": device_friendly_name,
"username": device_username,
"root_title": sync_root_title,
"sync_title": sync_title,
"metadata_type": sync_metadata_type,
"content_type": sync_content_type,
"rating_key": rating_key,
"state": status_state,
"item_count": status_item_count,
"item_complete_count": status_item_complete_count,
"item_downloaded_count": status_item_downloaded_count,
"item_downloaded_percent_complete": status_item_download_percent_complete,
"video_bitrate": settings_video_bitrate,
"audio_bitrate": settings_audio_bitrate,
"photo_quality": settings_photo_quality,
"video_quality": settings_video_quality,
"total_size": status_total_size,
"failure": status_failure,
"client_id": client_id,
"sync_id": sync_id
}
synced_items.append(sync_details)
return session.filter_session_info(synced_items, filter_key='user_id')
def delete_sync(self, client_id, sync_id):
logger.info("Tautulli PlexTV :: Deleting sync item '%s'." % sync_id)
self.delete_plextv_sync(client_id=client_id, sync_id=sync_id)
def get_server_connections(self, pms_identifier='', pms_ip='', pms_port=32400, include_https=True):
if not pms_identifier:
logger.error("Tautulli PlexTV :: Unable to retrieve server connections: no pms_identifier provided.")
return {}
plextv_resources = self.get_plextv_resources(include_https=include_https,
output_format='xml')
try:
xml_head = plextv_resources.getElementsByTagName('Device')
except Exception as e:
logger.warn("Tautulli PlexTV :: Unable to parse XML for get_server_urls: %s." % e)
return {}
# Function to get all connections for a device
def get_connections(device):
conn = []
connections = device.getElementsByTagName('Connection')
server = {'pms_identifier': helpers.get_xml_attr(device, 'clientIdentifier'),
'pms_name': helpers.get_xml_attr(device, 'name'),
'pms_version': helpers.get_xml_attr(device, 'productVersion'),
'pms_platform': helpers.get_xml_attr(device, 'platform'),
'pms_presence': helpers.get_xml_attr(device, 'presence'),
'pms_is_cloud': 1 if helpers.get_xml_attr(device, 'platform') == 'Cloud' else 0
}
for c in connections:
server_details = {'protocol': helpers.get_xml_attr(c, 'protocol'),
'address': helpers.get_xml_attr(c, 'address'),
'port': helpers.get_xml_attr(c, 'port'),
'uri': helpers.get_xml_attr(c, 'uri'),
'local': helpers.get_xml_attr(c, 'local')
}
conn.append(server_details)
server['connections'] = conn
return server
server = {}
# Try to match the device
for a in xml_head:
if helpers.get_xml_attr(a, 'clientIdentifier') == pms_identifier:
server = get_connections(a)
break
# Else no device match found
if not server:
# Try to match the PMS_IP and PMS_PORT
for a in xml_head:
if helpers.get_xml_attr(a, 'provides') == 'server':
connections = a.getElementsByTagName('Connection')
for connection in connections:
if helpers.get_xml_attr(connection, 'address') == pms_ip and \
helpers.get_xml_attr(connection, 'port') == str(pms_port):
server = get_connections(a)
break
if server.get('connections'):
break
return server
def get_server_times(self):
servers = self.get_plextv_server_list(output_format='xml')
server_times = {}
try:
xml_head = servers.getElementsByTagName('Server')
except Exception as e:
logger.warn("Tautulli PlexTV :: Unable to parse XML for get_server_times: %s." % e)
return {}
for a in xml_head:
if helpers.get_xml_attr(a, 'machineIdentifier') == jellypy.CONFIG.PMS_IDENTIFIER:
server_times = {"created_at": helpers.get_xml_attr(a, 'createdAt'),
"updated_at": helpers.get_xml_attr(a, 'updatedAt'),
"version": helpers.get_xml_attr(a, 'version')
}
break
return server_times
def discover(self, include_cloud=True, all_servers=False):
""" Query plex for all servers online. Returns the ones you own in a selectize format """
# Try to discover localhost server
local_machine_identifier = None
request_handler = http_handler.HTTPHandler(urls='http://127.0.0.1:32400', timeout=1,
ssl_verify=False, silent=True)
request = request_handler.make_request(uri='/identity', request_type='GET', output_format='xml')
if request:
xml_head = request.getElementsByTagName('MediaContainer')[0]
local_machine_identifier = xml_head.getAttribute('machineIdentifier')
local_server = {'httpsRequired': '0',
'clientIdentifier': local_machine_identifier,
'label': 'Local',
'ip': '127.0.0.1',
'port': '32400',
'uri': 'http://127.0.0.1:32400',
'local': '1',
'value': '127.0.0.1:32400',
'is_cloud': False
}
servers = self.get_plextv_resources(include_https=True, output_format='xml')
clean_servers = []
try:
xml_head = servers.getElementsByTagName('MediaContainer')
except Exception as e:
logger.warn("Tautulli PlexTV :: Failed to get servers from plex: %s." % e)
return []
for a in xml_head:
if a.getAttribute('size'):
if a.getAttribute('size') == '0':
return []
if a.getElementsByTagName('Device'):
devices = a.getElementsByTagName('Device')
for d in devices:
if helpers.get_xml_attr(d, 'presence') == '1' and \
helpers.get_xml_attr(d, 'owned') == '1' and \
helpers.get_xml_attr(d, 'provides') == 'server':
is_cloud = (helpers.get_xml_attr(d, 'platform').lower() == 'cloud')
if not include_cloud and is_cloud:
continue
connections = d.getElementsByTagName('Connection')
for c in connections:
if not all_servers:
# If this is a remote server don't show any local IPs.
if helpers.get_xml_attr(d, 'publicAddressMatches') == '0' and \
helpers.get_xml_attr(c, 'local') == '1':
continue
# If this is a local server don't show any remote IPs.
if helpers.get_xml_attr(d, 'publicAddressMatches') == '1' and \
helpers.get_xml_attr(c, 'local') == '0':
continue
if helpers.get_xml_attr(d, 'clientIdentifier') == local_machine_identifier:
local_server['httpsRequired'] = helpers.get_xml_attr(d, 'httpsRequired')
local_server['label'] = helpers.get_xml_attr(d, 'name')
clean_servers.append(local_server)
local_machine_identifier = None
server = {'httpsRequired': '1' if is_cloud else helpers.get_xml_attr(d, 'httpsRequired'),
'clientIdentifier': helpers.get_xml_attr(d, 'clientIdentifier'),
'label': helpers.get_xml_attr(d, 'name'),
'ip': helpers.get_xml_attr(c, 'address'),
'port': helpers.get_xml_attr(c, 'port'),
'uri': helpers.get_xml_attr(c, 'uri'),
'local': helpers.get_xml_attr(c, 'local'),
'value': helpers.get_xml_attr(c, 'address') + ':' + helpers.get_xml_attr(c,
'port'),
'is_cloud': is_cloud
}
clean_servers.append(server)
if local_machine_identifier:
clean_servers.append(local_server)
clean_servers.sort(key=lambda s: (s['label'], -int(s['local']), s['ip']))
return clean_servers
def get_plex_downloads(self):
logger.debug("Tautulli PlexTV :: Retrieving current server version.")
pms_connect = pmsconnect.PmsConnect()
pms_connect.set_server_version()
update_channel = pms_connect.get_server_update_channel()
logger.debug("Tautulli PlexTV :: Plex update channel is %s." % update_channel)
plex_downloads = self.get_plextv_downloads(plexpass=(update_channel == 'beta'))
try:
available_downloads = json.loads(plex_downloads)
except Exception as e:
logger.warn("Tautulli PlexTV :: Unable to load JSON for get_plex_updates.")
return {}
# Get the updates for the platform
pms_platform = common.PMS_PLATFORM_NAME_OVERRIDES.get(jellypy.CONFIG.PMS_PLATFORM, jellypy.CONFIG.PMS_PLATFORM)
platform_downloads = available_downloads.get('computer').get(pms_platform) or \
available_downloads.get('nas').get(pms_platform)
if not platform_downloads:
logger.error("Tautulli PlexTV :: Unable to retrieve Plex updates: Could not match server platform: %s."
% pms_platform)
return {}
v_old = helpers.cast_to_int(
"".join(v.zfill(4) for v in jellypy.CONFIG.PMS_VERSION.split('-')[0].split('.')[:4]))
v_new = helpers.cast_to_int(
"".join(v.zfill(4) for v in platform_downloads.get('version', '').split('-')[0].split('.')[:4]))
if not v_old:
logger.error("Tautulli PlexTV :: Unable to retrieve Plex updates: Invalid current server version: %s."
% jellypy.CONFIG.PMS_VERSION)
return {}
if not v_new:
logger.error("Tautulli PlexTV :: Unable to retrieve Plex updates: Invalid new server version: %s."
% platform_downloads.get('version'))
return {}
# Get proper download
releases = platform_downloads.get('releases', [{}])
release = next((r for r in releases if r['distro'] == jellypy.CONFIG.PMS_UPDATE_DISTRO and
r['build'] == jellypy.CONFIG.PMS_UPDATE_DISTRO_BUILD), releases[0])
download_info = {'update_available': v_new > v_old,
'platform': platform_downloads.get('name'),
'release_date': platform_downloads.get('release_date'),
'version': platform_downloads.get('version'),
'requirements': platform_downloads.get('requirements'),
'extra_info': platform_downloads.get('extra_info'),
'changelog_added': platform_downloads.get('items_added'),
'changelog_fixed': platform_downloads.get('items_fixed'),
'label': release.get('label'),
'distro': release.get('distro'),
'distro_build': release.get('build'),
'download_url': release.get('url'),
}
return download_info
def get_plexpass_status(self):
account_data = self.get_plextv_user_details(output_format='xml')
try:
subscription = account_data.getElementsByTagName('subscription')
except Exception as e:
logger.warn("Tautulli PlexTV :: Unable to parse XML for get_plexpass_status: %s." % e)
return False
if subscription and helpers.get_xml_attr(subscription[0], 'active') == '1':
jellypy.CONFIG.__setattr__('PMS_PLEXPASS', 1)
jellypy.CONFIG.write()
return True
else:
logger.debug("Tautulli PlexTV :: Plex Pass subscription not found.")
jellypy.CONFIG.__setattr__('PMS_PLEXPASS', 0)
jellypy.CONFIG.write()
return False
def get_devices_list(self):
devices = self.get_plextv_devices_list(output_format='xml')
try:
xml_head = devices.getElementsByTagName('Device')
except Exception as e:
logger.warn("Tautulli PlexTV :: Unable to parse XML for get_devices_list: %s." % e)
return []
devices_list = []
for a in xml_head:
device = {"device_name": helpers.get_xml_attr(a, 'name'),
"product": helpers.get_xml_attr(a, 'product'),
"product_version": helpers.get_xml_attr(a, 'productVersion'),
"platform": helpers.get_xml_attr(a, 'platform'),
"platform_version": helpers.get_xml_attr(a, 'platformVersion'),
"device": helpers.get_xml_attr(a, 'device'),
"model": helpers.get_xml_attr(a, 'model'),
"vendor": helpers.get_xml_attr(a, 'vendor'),
"provides": helpers.get_xml_attr(a, 'provides'),
"device_identifier": helpers.get_xml_attr(a, 'clientIdentifier'),
"device_id": helpers.get_xml_attr(a, 'id'),
"token": helpers.get_xml_attr(a, 'token')
}
devices_list.append(device)
return devices_list
def get_cloud_server_status(self):
cloud_status = self.cloud_server_status(output_format='xml')
try:
status_info = cloud_status.getElementsByTagName('info')
except Exception as e:
logger.warn("Tautulli PlexTV :: Unable to parse XML for get_cloud_server_status: %s." % e)
return False
for info in status_info:
servers = info.getElementsByTagName('server')
for s in servers:
if helpers.get_xml_attr(s, 'address') == jellypy.CONFIG.PMS_IP:
if helpers.get_xml_attr(info, 'running') == '1':
return True
else:
return False
def get_plex_account_details(self):
account_data = self.get_plextv_user_details(output_format='xml')
try:
xml_head = account_data.getElementsByTagName('user')
except Exception as e:
logger.warn("Tautulli PlexTV :: Unable to parse XML for get_plex_account_details: %s." % e)
return None
for a in xml_head:
account_details = {"user_id": helpers.get_xml_attr(a, 'id'),
"username": helpers.get_xml_attr(a, 'username'),
"thumb": helpers.get_xml_attr(a, 'thumb'),
"email": helpers.get_xml_attr(a, 'email'),
"is_home_user": helpers.get_xml_attr(a, 'home'),
"is_restricted": helpers.get_xml_attr(a, 'restricted'),
"filter_all": helpers.get_xml_attr(a, 'filterAll'),
"filter_movies": helpers.get_xml_attr(a, 'filterMovies'),
"filter_tv": helpers.get_xml_attr(a, 'filterTelevision'),
"filter_music": helpers.get_xml_attr(a, 'filterMusic'),
"filter_photos": helpers.get_xml_attr(a, 'filterPhotos'),
"user_token": helpers.get_xml_attr(a, 'authToken')
}
return account_details
def get_geoip_lookup(self, ip_address=''):
if not ip_address or not helpers.is_valid_ip(ip_address):
return
geoip_data = self.get_plextv_geoip(ip_address=ip_address, output_format='xml')
try:
xml_head = geoip_data.getElementsByTagName('location')
except Exception as e:
logger.warn(u"Tautulli PlexTV :: Unable to parse XML for get_geoip_lookup: %s." % e)
return None
for a in xml_head:
coordinates = helpers.get_xml_attr(a, 'coordinates').split(',')
latitude = longitude = None
if len(coordinates) == 2:
latitude, longitude = [helpers.cast_to_float(c) for c in coordinates]
geo_info = {"code": helpers.get_xml_attr(a, 'code') or None,
"country": helpers.get_xml_attr(a, 'country') or None,
"region": helpers.get_xml_attr(a, 'subdivisions') or None,
"city": helpers.get_xml_attr(a, 'city') or None,
"postal_code": helpers.get_xml_attr(a, 'postal_code') or None,
"timezone": helpers.get_xml_attr(a, 'time_zone') or None,
"latitude": latitude,
"longitude": longitude,
"continent": None, # keep for backwards compatibility with GeoLite2
"accuracy": None # keep for backwards compatibility with GeoLite2
}
return geo_info

File diff suppressed because it is too large Load Diff

View File

@@ -25,7 +25,6 @@ from jellypy import datatables
from jellypy import helpers from jellypy import helpers
from jellypy import libraries from jellypy import libraries
from jellypy import logger from jellypy import logger
from jellypy import plextv
from jellypy import session from jellypy import session

View File

@@ -33,7 +33,6 @@ from jellypy.database import MonitorDatabase
from jellypy.helpers import timestamp from jellypy.helpers import timestamp
from jellypy.password import check_hash from jellypy.password import check_hash
from jellypy.users import Users, refresh_users from jellypy.users import Users, refresh_users
from jellypy.plextv import PlexTV
# Monkey patch SameSite support into cookies. # Monkey patch SameSite support into cookies.
# https://stackoverflow.com/a/50813092 # https://stackoverflow.com/a/50813092
@@ -51,21 +50,22 @@ def plex_user_login(username=None, password=None, token=None, headers=None):
user_token = None user_token = None
user_id = None user_id = None
# Try to login to Plex.tv to check if the user has a vaild account # TODO: Jellyfin
if username and password: # # Try to login to Plex.tv to check if the user has a vaild account
plex_tv = PlexTV(username=username, password=password, headers=headers) # if username and password:
plex_user = plex_tv.get_token() # plex_tv = PlexTV(username=username, password=password, headers=headers)
if plex_user: # plex_user = plex_tv.get_token()
user_token = plex_user['auth_token'] # if plex_user:
user_id = plex_user['user_id'] # user_token = plex_user['auth_token']
elif token: # user_id = plex_user['user_id']
plex_tv = PlexTV(token=token, headers=headers) # elif token:
plex_user = plex_tv.get_plex_account_details() # plex_tv = PlexTV(token=token, headers=headers)
if plex_user: # plex_user = plex_tv.get_plex_account_details()
user_token = token # if plex_user:
user_id = plex_user['user_id'] # user_token = token
else: # user_id = plex_user['user_id']
return None # else:
# return None
if user_token and user_id: if user_token and user_id:
# Try to retrieve the user from the database. # Try to retrieve the user from the database.
@@ -86,10 +86,12 @@ def plex_user_login(username=None, password=None, token=None, headers=None):
if not jellypy.CONFIG.ALLOW_GUEST_ACCESS: if not jellypy.CONFIG.ALLOW_GUEST_ACCESS:
return None return None
# The user is in the database, and guest access is enabled, so try to retrieve a server token. # TODO: Jellyfin
# If a server token is returned, then the user is a valid friend of the server. # # The user is in the database, and guest access is enabled, so try to retrieve a server token.
plex_tv = PlexTV(token=user_token, headers=headers) # # If a server token is returned, then the user is a valid friend of the server.
server_token = plex_tv.get_server_token() # plex_tv = PlexTV(token=user_token, headers=headers)
# server_token = plex_tv.get_server_token()
server_token = None
if server_token: if server_token:
# Register the new user / update the access tokens. # Register the new user / update the access tokens.

File diff suppressed because it is too large Load Diff