From 3852275b7451df3527d96e162b0354678b358843 Mon Sep 17 00:00:00 2001 From: Giovanni Harting <539@idlegandalf.com> Date: Sat, 6 Feb 2021 18:41:24 +0100 Subject: [PATCH] =?UTF-8?q?Jellyfin=20Login=20=E2=9C=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 8 +- data/interfaces/default/welcome.html | 43 ++++------ jellypy/helpers.py | 13 --- jellypy/jellyfin.py | 23 +++--- jellypy/webserve.py | 115 ++++++++++++--------------- 5 files changed, 85 insertions(+), 117 deletions(-) diff --git a/README.md b/README.md index 0c0a064c..bc001f25 100644 --- a/README.md +++ b/README.md @@ -19,10 +19,10 @@ not well documented (read as: not documented at all). ## Major Differences compared to Tautulli -* No Plex/PMS Support -* Removed Google Analytics -* Removed Python2 support -* Removed import feature from varius abondonded projects +* Dropped Plex/PMS Support +* Dropped Google Analytics +* Dropped Python2 support +* Dropped import from varius abondonded projects ## Installation & Support diff --git a/data/interfaces/default/welcome.html b/data/interfaces/default/welcome.html index 158570ad..ddfb6eeb 100644 --- a/data/interfaces/default/welcome.html +++ b/data/interfaces/default/welcome.html @@ -176,8 +176,7 @@ from jellypy import common, helpers - - Verify + Verify @@ -185,7 +184,7 @@ from jellypy import common, helpers

Activity Logging

- Tautulli will keep a history of all streaming activity on your Plex server. + JellyPy will keep a history of all streaming activity on your Jellyfin server.

@@ -216,7 +215,7 @@ from jellypy import common, helpers

Notifications

- Tautulli can send a wide variety of notifications to alert you of activity on your Plex + JellyPy can send a wide variety of notifications to alert you of activity on your Jellyfin server.

@@ -225,20 +224,6 @@ from jellypy import common, helpers wizard.

-
- -
-

Database Import

-
-

- If you have an existing Tautulli, PlexWatch, or Plexivity database, you can import the data - into Tautulli. -

-

- To import a database, navigate to the Settings page - and to the Import & Backups tab after you have completed this setup wizard. -

-
@@ -266,7 +251,6 @@ from jellypy import common, helpers
-
@@ -308,7 +292,7 @@ from jellypy import common, helpers return retValue; } - function validatejellyfinip(el) { + function validateJellyfinIp(el) { var valid_jellyfin_ip = el.val(); var retValue = {}; @@ -324,7 +308,7 @@ from jellypy import common, helpers return retValue; } - function validatejellyfintoken(el) { + function validateJellyfinToken(el) { var valid_jellyfin_token = el.val(); var retValue = {}; @@ -518,24 +502,27 @@ from jellypy import common, helpers var jellyfin_verified = false; var authenticated = false; - $("#verify-plex-server").click(function () { + $("#verify-jellyfin-server").click(function () { if (!(jellyfin_verified)) { var jellyfin_ip = $("#jellyfin_ip").val().trim(); var jellyfin_port = $("#jellyfin_port").val().trim(); - var jellyfin_identifier = $("#jellyfin_identifier").val(); var jellyfin_ssl = $("#jellyfin_ssl").val(); var jellyfin_is_remote = $("#jellyfin_is_remote").val(); + var jellyfin_user = $("#jellyfin_user").val().trim(); + var jellyfin_password = $("#jellyfin_password").val(); + if ((jellyfin_ip !== '') || (jellyfin_port !== '')) { $("#jellyfin-verify-status").html('  Verifying server...'); $('#jellyfin-verify-status').fadeIn('fast'); $.ajax({ - url: 'get_server_id', + url: 'check_login', data: { hostname: jellyfin_ip, port: jellyfin_port, - identifier: jellyfin_identifier, ssl: jellyfin_ssl, - remote: jellyfin_is_remote + remote: jellyfin_is_remote, + user: jellyfin_user, + password: jellyfin_password }, cache: true, async: true, @@ -549,12 +536,12 @@ from jellypy import common, helpers var identifier = result.identifier; if (identifier) { $("#jellyfin_identifier").val(identifier); - $("#jellyfin-verify-status").html('  Server found!'); + $("#jellyfin-verify-status").html('  Login successfull!'); $('#jellyfin-verify-status').fadeIn('fast'); jellyfin_verified = true; $("#jellyfin_valid").val("valid"); } else { - $("#jellyfin-verify-status").html('  This is not a Plex Server!'); + $("#jellyfin-verify-status").html('  This is not a Jellyfin Server!'); $('#jellyfin-verify-status').fadeIn('fast'); } } diff --git a/jellypy/helpers.py b/jellypy/helpers.py index 1522cc5c..f432dc9c 100644 --- a/jellypy/helpers.py +++ b/jellypy/helpers.py @@ -653,19 +653,6 @@ def is_public_ip(host): return False -def get_ip(host): - ip_address = '' - if is_valid_ip(host): - return host - elif not re.match(r'^[0-9]+(?:\.[0-9]+){3}(?!\d*-[a-z0-9]{6})$', host): - try: - ip_address = socket.getaddrinfo(host, None)[0][4][0] - logger.debug("IP Checker :: Resolved %s to %s." % (host, ip_address)) - except: - logger.error("IP Checker :: Bad IP or hostname provided: %s." % host) - return ip_address - - def is_valid_ip(address): try: return IP(address) diff --git a/jellypy/jellyfin.py b/jellypy/jellyfin.py index 04a45636..ab543b26 100644 --- a/jellypy/jellyfin.py +++ b/jellypy/jellyfin.py @@ -35,11 +35,13 @@ class Jellyfin(object): PRODUCT, RELEASE, PRODUCT, jellypy.CONFIG.JELLYFIN_CLIENT_UUID ) self.jf.config.data["http.user_agent"] = PRODUCT - self.jf.config.data["auth.ssl"] = not jellypy.CONFIG.JELLYFIN_SSL + self.jf.config.data["auth.ssl"] = jellypy.CONFIG.JELLYFIN_SSL self.url = url + self.id = None + self.token = token - if token: - self.login(token=token) + if self.token: + self.login() def get_library(self, section_id): return self.jf.library.sectionByID(str(section_id)) @@ -50,22 +52,23 @@ class Jellyfin(object): def get_item(self, rating_key): return self.jf.fetchItem(rating_key) - def login(self, user=None, password=None, token=None) -> bool: - if user and password: + def login(self, user=None, password=None) -> bool: + if user and password and self.url: self.jf.auth.connect_to_address(self.url) result = self.jf.auth.login(self.url, user, password) if "AccessToken" in result: credentials = self.jf.auth.credentials.get_credentials() pprint.pprint(credentials) - server = credentials["Servers"][0] - server["uuid"] = server["Id"] - server["username"] = user - + self.id = credentials["Servers"][0]["Id"] # jellypy.CONFIG.JELLYFIN_TOKEN = # # self._connect_client(server) # self.credentials.append(server) # self.save_credentials() return True - return False + if self.token and self.url: + # TODO: Add token auth + pass + + return False diff --git a/jellypy/webserve.py b/jellypy/webserve.py index a232d516..96d602e8 100644 --- a/jellypy/webserve.py +++ b/jellypy/webserve.py @@ -20,6 +20,7 @@ import csv import json import linecache import os +import re import shutil import sys import threading @@ -30,7 +31,6 @@ from urllib.parse import urlencode import cherrypy import mako.exceptions import mako.template -import websocket from cherrypy import NotFound from cherrypy.lib.static import serve_file, serve_fileobj, serve_download from mako.lookup import TemplateLookup @@ -57,6 +57,7 @@ from jellypy import versioncheck from jellypy import webstart from jellypy.api2 import API2 from jellypy.helpers import checked, addtoapi, create_https_certificates, build_datatables_json, sanitize_out +from jellypy.jellyfin import Jellyfin from jellypy.password import make_hash from jellypy.session import get_session_info, get_session_user_id, allow_session_user, allow_session_library from jellypy.webauth import AuthController, requireAuth, member_of, check_auth @@ -4035,14 +4036,16 @@ class WebInterface(object): @cherrypy.tools.json_out() @requireAuth(member_of("admin")) @addtoapi() - def get_server_id(self, hostname=None, port=None, identifier=None, ssl=0, remote=0, manual=0, - get_url=False, test_websocket=False, **kwargs): - """ Get the JELLYFIN server identifier. + def check_login(self, hostname=None, port=None, ssl=0, remote=0, manual=0, user=None, password=None, + get_url=False, test_websocket=False, **kwargs): + """ Try Jellyfin Login. ``` Required parameters: hostname (str): 'localhost' or '192.160.0.10' - port (int): 32400 + port (int): 8096 + user (str): Jellyfin user + password (str): Jellyfin password Optional parameters: ssl (int): 0 or 1 @@ -4054,66 +4057,54 @@ class WebInterface(object): ``` """ # Attempt to get the pms_identifier from plex.tv if the server is published - # Works for all JELLYFIN SSL settings - if not identifier and hostname and port: - pass - # TODO: Jellyfin - # plex_tv = plextv.PlexTV() - # servers = plex_tv.discover() - # ip_address = get_ip(hostname) + # Works for all Jellyfin SSL settings + result = {"identifier": None} + if hostname and port and user and password: + path_regex = re.compile("^(https?://)?([^/:]+)(:[0-9]+)?(/.*)?$") + + protocol, host, port, path = path_regex.match(hostname + ":" + port).groups() + + if not protocol: + protocol = "http://" + + if protocol == "http://" and not port: + port = "8096" + + server = "".join(filter(bool, (protocol, host, port, path))) + + jf = Jellyfin(server) + if jf.login(user, password): + result = {'identifier': jf.id} + + # if identifier: + # if helpers.bool_true(get_url): + # server = self.get_server_resources(jellyfin_ip=hostname, + # jellyfin_port=port, + # jellyfin_ssl=ssl, + # jellyfin_is_remote=remote, + # jellyfin_url_manual=manual, + # jellyfin_identifier=identifier) + # result['url'] = server['jellyfin_url'] + # result['ws'] = None # - # for server in servers: - # if (server['ip'] == hostname or server['ip'] == ip_address) and server['port'] == port: - # identifier = server['clientIdentifier'] - # break + # if helpers.bool_true(test_websocket): + # # Quick test websocket connection + # ws_url = result['url'].replace('http', 'ws', 1) + '/:/websockets/notifications' + # header = ['X-Plex-Token: %s' % jellypy.CONFIG.JELLYFIN_TOKEN] # - # # Fallback to checking /identity endpoint if the server is unpublished - # # Cannot set SSL settings on the JELLYFIN if unpublished so 'http' is okay - # if not identifier: - # scheme = 'https' if helpers.cast_to_int(ssl) else 'http' - # url = '{scheme}://{hostname}:{port}'.format(scheme=scheme, hostname=hostname, port=port) - # uri = '/identity' - # - # request_handler = http_handler.HTTPHandler(urls=url, - # ssl_verify=False) - # request = request_handler.make_request(uri=uri, - # request_type='GET', - # output_format='xml') - # if request: - # xml_head = request.getElementsByTagName('MediaContainer')[0] - # identifier = xml_head.getAttribute('machineIdentifier') - - result = {'identifier': identifier} - - if identifier: - if helpers.bool_true(get_url): - server = self.get_server_resources(jellyfin_ip=hostname, - jellyfin_port=port, - jellyfin_ssl=ssl, - jellyfin_is_remote=remote, - jellyfin_url_manual=manual, - jellyfin_identifier=identifier) - result['url'] = server['jellyfin_url'] - result['ws'] = None - - if helpers.bool_true(test_websocket): - # Quick test websocket connection - ws_url = result['url'].replace('http', 'ws', 1) + '/:/websockets/notifications' - header = ['X-Plex-Token: %s' % jellypy.CONFIG.JELLYFIN_TOKEN] - - logger.debug("Testing websocket connection...") - try: - test_ws = websocket.create_connection(ws_url, header=header) - test_ws.close() - logger.debug("Websocket connection test successful.") - result['ws'] = True - except (websocket.WebSocketException, IOError, Exception) as e: - logger.error("Websocket connection test failed: %s" % e) - result['ws'] = False + # logger.debug("Testing websocket connection...") + # try: + # test_ws = websocket.create_connection(ws_url, header=header) + # test_ws.close() + # logger.debug("Websocket connection test successful.") + # result['ws'] = True + # except (websocket.WebSocketException, IOError, Exception) as e: + # logger.error("Websocket connection test failed: %s" % e) + # result['ws'] = False return result else: - logger.warn('Unable to retrieve the JELLYFIN identifier.') + logger.warn('Unable to retrieve the Jellyfin identifier.') return result @cherrypy.expose @@ -4480,8 +4471,8 @@ class WebInterface(object): @addtoapi('jellyfin_image_proxy') def real_jellyfin_image_proxy(self, img=None, rating_key=None, width=750, height=1000, - opacity=100, background='000000', blur=0, img_format='png', - fallback=None, refresh=False, clip=False, **kwargs): + opacity=100, background='000000', blur=0, img_format='png', + fallback=None, refresh=False, clip=False, **kwargs): """ Gets an image from the JELLYFIN and saves it to the image cache directory. ```