total rewrite while resolving #146.
Now able to read watched status from Tautulli and apply to any user on any owned server.
This commit is contained in:
parent
80557f4a61
commit
e605979a16
@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env python
|
||||
"""
|
||||
Description: Sync the watch status from one user to another. Either by user or user/libraries
|
||||
Description: Sync the watch status from one user to another across multiple servers including from Tautulli
|
||||
Author: Blacktwin
|
||||
Requires: requests, plexapi, argparse
|
||||
|
||||
@ -31,32 +31,35 @@ Script Arguments:
|
||||
Taultulli > Settings > Notification Agents > New Script > Script Arguments:
|
||||
|
||||
Select: Notify on Watched
|
||||
Arguments: --ratingKey {rating_key} --userTo "Username2=Server1" "Username3=Server1" --userFrom {username}={server_name}
|
||||
Arguments: --ratingKey {rating_key} --userFrom Tautulli=Tautulli --userTo "Username2=Server1" "Username3=Server1"
|
||||
|
||||
Save
|
||||
Close
|
||||
|
||||
Example:
|
||||
Set in Tautulli in script notification agent or run manually
|
||||
Set in Tautulli in script notification agent (above) or run manually (below)
|
||||
|
||||
sync_watch_status.py --userFrom USER1=Server --userTo USER2=Server --libraries Movies
|
||||
- Synced watch status of {title from library} to {USER2}'s account.
|
||||
sync_watch_status.py --userFrom USER1=Server1 --userTo USER2=Server1 --libraries Movies
|
||||
- Synced watch status from Server1 {title from library} to {USER2}'s account on Server1.
|
||||
|
||||
sync_watch_status.py --userFrom USER1=Server --userTo USER2=Server USER3=Server --allLibraries
|
||||
- Synced watch status of {title from library} to {USER2 or USER3}'s account.
|
||||
sync_watch_status.py --userFrom USER1=Server2 --userTo USER2=Server1 USER3=Server1 --libraries Movies "TV Shows"
|
||||
- Synced watch status from Server2 {title from library} to {USER2 or USER3}'s account on Server1.
|
||||
|
||||
Excluding;
|
||||
--libraries becomes excluded if --allLibraries is set
|
||||
sync_watch_status.py --userFrom USER1=Server --userTo USER2=Server --allLibraries --libraries Movies
|
||||
- Shared [all libraries but Movies] with USER.
|
||||
sync_watch_status.py --userFrom USER1=Tautulli --userTo USER2=Server1 USER3=Server2 --libraries Movies "TV Shows"
|
||||
- Synced watch statuses from Tautulli {title from library} to {USER2 or USER3}'s account on selected servers.
|
||||
|
||||
"""
|
||||
import sys
|
||||
import requests
|
||||
import argparse
|
||||
from plexapi.myplex import MyPlexAccount
|
||||
from plexapi.server import PlexServer, CONFIG
|
||||
from plexapi.server import PlexServer
|
||||
from plexapi.server import CONFIG
|
||||
from requests import Session
|
||||
from requests.adapters import HTTPAdapter
|
||||
from requests.exceptions import RequestException
|
||||
|
||||
import pprint
|
||||
|
||||
pp = pprint.PrettyPrinter(indent=4)
|
||||
|
||||
# Using CONFIG file
|
||||
PLEX_TOKEN = ''
|
||||
@ -64,206 +67,441 @@ TAUTULLI_URL = ''
|
||||
TAUTULLI_APIKEY = ''
|
||||
|
||||
if not PLEX_TOKEN:
|
||||
PLEX_TOKEN = CONFIG.data['auth'].get('server_token', '')
|
||||
PLEX_TOKEN = CONFIG.data['auth'].get('server_token')
|
||||
if not TAUTULLI_URL:
|
||||
TAUTULLI_URL = CONFIG.data['auth'].get('tautulli_baseurl')
|
||||
if not TAUTULLI_APIKEY:
|
||||
TAUTULLI_APIKEY = CONFIG.data['auth'].get('tautulli_apikey')
|
||||
|
||||
|
||||
sess = requests.Session()
|
||||
# Ignore verifying the SSL certificate
|
||||
sess.verify = False # '/path/to/certfile'
|
||||
# If verify is set to a path to a directory,
|
||||
# the directory must have been processed using the c_rehash utility supplied
|
||||
# with OpenSSL.
|
||||
if sess.verify is False:
|
||||
# Disable the warning that the request is insecure, we know that...
|
||||
import urllib3
|
||||
|
||||
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
|
||||
|
||||
account = MyPlexAccount(PLEX_TOKEN)
|
||||
|
||||
# todo-me This is cleaned up. Should only connect to servers that are selected
|
||||
sections_lst = []
|
||||
user_servers = {}
|
||||
admin_servers = {}
|
||||
server_users = account.users()
|
||||
user_server_dict = {'data': {}}
|
||||
user_data = user_server_dict['data']
|
||||
|
||||
# Finding and connecting to owned servers.
|
||||
print('Connecting to admin owned servers.')
|
||||
for resource in account.resources():
|
||||
if 'server' in [resource.provides] and resource.ownerid == 0:
|
||||
server_connect = resource.connect()
|
||||
admin_servers[resource.name] = server_connect
|
||||
# Pull section names to check against
|
||||
server_sections = [section.title for section in server_connect.library.sections()]
|
||||
sections_lst += server_sections
|
||||
|
||||
sections_lst = list(set(sections_lst))
|
||||
|
||||
# Add admin account
|
||||
user_data[account.title] = {'account': account,
|
||||
'servers': admin_servers}
|
||||
|
||||
# Finding what user has access to which admin owned servers
|
||||
for user in server_users:
|
||||
for server in user.servers:
|
||||
if admin_servers.get(server.name):
|
||||
user_servers[server.name] = admin_servers.get(server.name)
|
||||
if not user_data.get(user.title):
|
||||
user_data[user.title] = {'account': user,
|
||||
'servers': user_servers}
|
||||
|
||||
# todo-me Add Tautulli history for syncing watch statuses from Tautulli to Plex
|
||||
def get_history(user_id, media_type):
|
||||
# Get the user history from Tautulli.
|
||||
payload = {'apikey': TAUTULLI_APIKEY,
|
||||
'cmd': 'get_history',
|
||||
'user_id': user_id,
|
||||
'media_type': media_type}
|
||||
|
||||
try:
|
||||
r = requests.get(TAUTULLI_URL.rstrip('/') + '/api/v2', params=payload)
|
||||
response = r.json()
|
||||
res_data = response['response']['data']['data']
|
||||
|
||||
except Exception as e:
|
||||
sys.stderr.write("Tautulli API 'get_history' request failed: {0}.".format(e))
|
||||
VERIFY_SSL = False
|
||||
|
||||
|
||||
def get_account(user, server):
|
||||
class Connection:
|
||||
def __init__(self, url=None, apikey=None, verify_ssl=False):
|
||||
self.url = url
|
||||
self.apikey = apikey
|
||||
self.session = Session()
|
||||
self.adapters = HTTPAdapter(max_retries=3,
|
||||
pool_connections=1,
|
||||
pool_maxsize=1,
|
||||
pool_block=True)
|
||||
self.session.mount('http://', self.adapters)
|
||||
self.session.mount('https://', self.adapters)
|
||||
|
||||
# Ignore verifying the SSL certificate
|
||||
if verify_ssl is False:
|
||||
self.session.verify = False
|
||||
# Disable the warning that the request is insecure, we know that...
|
||||
import urllib3
|
||||
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
|
||||
|
||||
|
||||
class Library(object):
|
||||
def __init__(self, data=None):
|
||||
d = data or {}
|
||||
self.title = d['section_name']
|
||||
self.key = d['section_id']
|
||||
|
||||
|
||||
class Metadata(object):
|
||||
def __init__(self, data=None):
|
||||
d = data or {}
|
||||
self.type = d['media_type']
|
||||
self.grandparentTitle = d['grandparent_title']
|
||||
self.parentIndex = d['parent_media_index']
|
||||
self.index = d['media_index']
|
||||
if self.type == 'episode':
|
||||
ep_name = d['full_title'].partition('-')[-1]
|
||||
self.title = ep_name.lstrip()
|
||||
else:
|
||||
self.title = d['full_title']
|
||||
|
||||
# For History
|
||||
try:
|
||||
if d['watched_status']:
|
||||
self.watched_status = d['watched_status']
|
||||
except KeyError:
|
||||
pass
|
||||
# For Metadata
|
||||
try:
|
||||
if d["library_name"]:
|
||||
self.libraryName = d['library_name']
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
|
||||
class Tautulli:
|
||||
def __init__(self, connection):
|
||||
self.connection = connection
|
||||
|
||||
def _call_api(self, cmd, payload, method='GET'):
|
||||
payload['cmd'] = cmd
|
||||
payload['apikey'] = self.connection.apikey
|
||||
|
||||
try:
|
||||
response = self.connection.session.request(method, self.connection.url + '/api/v2', params=payload)
|
||||
except RequestException as e:
|
||||
print("Tautulli request failed for cmd '{}'. Invalid Tautulli URL? Error: {}".format(cmd, e))
|
||||
return
|
||||
|
||||
try:
|
||||
response_json = response.json()
|
||||
except ValueError:
|
||||
print("Failed to parse json response for Tautulli API cmd '{}'".format(cmd))
|
||||
return
|
||||
|
||||
if response_json['response']['result'] == 'success':
|
||||
return response_json['response']['data']
|
||||
else:
|
||||
error_msg = response_json['response']['message']
|
||||
print("Tautulli API cmd '{}' failed: {}".format(cmd, error_msg))
|
||||
return
|
||||
|
||||
def get_watched_history(self, user, section_id, start, length):
|
||||
"""Call Tautulli's get_history api endpoint"""
|
||||
payload = {"user": user,
|
||||
"section_id": section_id,
|
||||
'start': start,
|
||||
'length': length,
|
||||
'order_column': 'full_title',
|
||||
'order_dir': 'asc'}
|
||||
|
||||
history = self._call_api('get_history', payload)
|
||||
|
||||
return [d for d in history['data'] if d['watched_status'] == 1]
|
||||
|
||||
def get_metadata(self, rating_key):
|
||||
"""Call Tautulli's get_metadata api endpoint"""
|
||||
|
||||
payload = {"rating_key": rating_key}
|
||||
return self._call_api('get_metadata', payload)
|
||||
|
||||
def get_libraries(self):
|
||||
"""Call Tautulli's get_libraries api endpoint"""
|
||||
|
||||
payload = {}
|
||||
return self._call_api('get_libraries', payload)
|
||||
|
||||
|
||||
class Plex:
|
||||
def __init__(self, token, url=None):
|
||||
if token and not url:
|
||||
self.account = MyPlexAccount(token)
|
||||
if token and url:
|
||||
session = Connection().session
|
||||
self.server = PlexServer(baseurl=url, token=token, session=session)
|
||||
|
||||
def admin_servers(self):
|
||||
"""
|
||||
Returns
|
||||
-------
|
||||
data: dict
|
||||
"""
|
||||
resources = {}
|
||||
for resource in self.account.resources():
|
||||
if 'server' in [resource.provides] and resource.owned == True:
|
||||
resources[resource.name] = resource
|
||||
|
||||
return resources
|
||||
|
||||
def all_users(self):
|
||||
"""
|
||||
Returns
|
||||
-------
|
||||
data: dict
|
||||
"""
|
||||
users = {self.account.title: self.account}
|
||||
for user in self.account.users():
|
||||
users[user.title] = user
|
||||
|
||||
return users
|
||||
|
||||
def all_sections(self):
|
||||
"""
|
||||
Returns
|
||||
-------
|
||||
data: dict
|
||||
"""
|
||||
data = {}
|
||||
servers = self.admin_servers()
|
||||
print('Connecting to admin server(s) for section info...')
|
||||
for name, server in servers.items():
|
||||
connect = server.connect()
|
||||
sections = {section.title: section for section in connect.library.sections()}
|
||||
data[name] = sections
|
||||
|
||||
return data
|
||||
|
||||
def users_access(self):
|
||||
"""
|
||||
Returns
|
||||
-------
|
||||
data: dict
|
||||
"""
|
||||
all_users = self.all_users().values()
|
||||
admin_servers = self.admin_servers()
|
||||
all_sections = self.all_sections()
|
||||
|
||||
data = {self.account.title: {"account": self.account}}
|
||||
|
||||
for user in all_users:
|
||||
if not data.get(user.title):
|
||||
servers = []
|
||||
for server in user.servers:
|
||||
if admin_servers.get(server.name):
|
||||
access = {}
|
||||
sections = {section.title: section for section in server.sections()
|
||||
if section.shared == True}
|
||||
access['server'] = {server.name: admin_servers.get(server.name)}
|
||||
access['sections'] = sections
|
||||
servers += [access]
|
||||
data[user.title] = {'account': user,
|
||||
'access': servers}
|
||||
else:
|
||||
# Admin account
|
||||
servers = []
|
||||
for name, server in admin_servers.items():
|
||||
access = {}
|
||||
sections = all_sections.get(name)
|
||||
access['server'] = {name: server}
|
||||
access['sections'] = sections
|
||||
servers += [access]
|
||||
data[user.title] = {'account': user,
|
||||
'access': servers}
|
||||
return data
|
||||
|
||||
|
||||
def connect_to_server(server_obj, user_account):
|
||||
"""
|
||||
Parameters
|
||||
----------
|
||||
server_obj: class
|
||||
user_account: class
|
||||
|
||||
Returns
|
||||
-------
|
||||
user_connection.server: class
|
||||
"""
|
||||
server_name = server_obj.name
|
||||
user = user_account.title
|
||||
|
||||
print('Connecting {} to {}...'.format(user, server_name))
|
||||
server_connection = server_obj.connect()
|
||||
baseurl = server_connection._baseurl.split('.')
|
||||
url = ''.join([baseurl[0].replace('-', '.'),
|
||||
baseurl[-1].replace('direct', '')])
|
||||
if user_account.title == Plex(PLEX_TOKEN).account.title:
|
||||
token = PLEX_TOKEN
|
||||
else:
|
||||
token = user_account.get_token(server_connection.machineIdentifier)
|
||||
|
||||
user_connection = Plex(url=url, token=token)
|
||||
|
||||
return user_connection.server
|
||||
|
||||
|
||||
def check_users_access(user, server_name, libraries=None):
|
||||
"""
|
||||
Parameters
|
||||
----------
|
||||
user: str
|
||||
User's name
|
||||
server: str
|
||||
Server's name
|
||||
server_name: str
|
||||
libraries: list
|
||||
|
||||
Returns
|
||||
-------
|
||||
User server class
|
||||
|
||||
server_connection: class
|
||||
"""
|
||||
print('Checking {} on {}'.format(user, server))
|
||||
if user_server_dict['data'][user]['servers'].get(server):
|
||||
user_server = user_server_dict['data'][user]['servers'].get(server)
|
||||
baseurl = user_server._baseurl.split('.')
|
||||
url = ''.join([baseurl[0].replace('-', '.'),
|
||||
baseurl[-1].replace('direct', '')])
|
||||
if user == MyPlexAccount(PLEX_TOKEN).title:
|
||||
token = PLEX_TOKEN
|
||||
else:
|
||||
userAccount = user_server.myPlexAccount().user(user)
|
||||
token = userAccount.get_token(user_server.machineIdentifier)
|
||||
account = PlexServer(baseurl=url, token=token, session=sess)
|
||||
return account
|
||||
else:
|
||||
print('{} is not shared to {}'.format(user, server))
|
||||
try:
|
||||
_user = plex_admin.users_access().get(user)
|
||||
for access in _user['access']:
|
||||
server = access.get("server")
|
||||
# Check user access to server
|
||||
if server.get(server_name):
|
||||
server_obj = server.get(server_name)
|
||||
# If syncing by libraries, check library access
|
||||
if libraries:
|
||||
library_check = any(lib.title in access.get("sections").keys() for lib in libraries)
|
||||
# Check user access to library
|
||||
if library_check:
|
||||
server_connection = connect_to_server(server_obj, _user['account'])
|
||||
return server_connection
|
||||
|
||||
elif not library_check:
|
||||
print("User does not have access to this library.")
|
||||
# Not syncing by libraries
|
||||
else:
|
||||
server_connection = connect_to_server(server_obj, _user['account'])
|
||||
return server_connection
|
||||
# else:
|
||||
# print("User does not have access to this server: {}.".format(server_name))
|
||||
except KeyError:
|
||||
print('User name is incorrect.')
|
||||
print(", ".join(plex_admin.all_users().keys()))
|
||||
exit()
|
||||
|
||||
|
||||
def mark_watached(sectionFrom, accountTo, userTo):
|
||||
def sync_watch_status(watched, section, accountTo, userTo):
|
||||
"""
|
||||
Parameters
|
||||
----------
|
||||
sectionFrom: class
|
||||
watched: list
|
||||
section: class
|
||||
Section class of sync from server
|
||||
accountTo: class
|
||||
userTo: str
|
||||
User's server class of sync to user
|
||||
|
||||
"""
|
||||
# Check sections for watched items
|
||||
print('Marking watched...')
|
||||
sectionTo = accountTo.library.section(sectionFrom.title)
|
||||
for item in sectionFrom.search(unwatched=False):
|
||||
title = item.title.encode('utf-8')
|
||||
sectionTo = accountTo.library.section(section)
|
||||
for item in watched:
|
||||
try:
|
||||
# Check movie media type
|
||||
if item.type == 'movie':
|
||||
watch_check = sectionTo.get(item.title)
|
||||
fetch_check = sectionTo.fetchItem(watch_check.key)
|
||||
if not fetch_check.isWatched:
|
||||
fetch_check.markWatched()
|
||||
print('Synced watch status of {} to {}\'s account.'.format(title, userTo))
|
||||
# Check show media type
|
||||
elif item.type == 'show':
|
||||
for episode in sectionFrom.searchEpisodes(unwatched=False, title=title):
|
||||
ep_title = episode.title.encode('utf-8')
|
||||
watch_check = sectionTo.get(item.title)
|
||||
fetch_check = sectionTo.fetchItem(watch_check.key)
|
||||
if not fetch_check.isWatched:
|
||||
fetch_check.markWatched()
|
||||
print('Synced watch status of {} - {} to {}\'s account.'.format(title, ep_title, userTo))
|
||||
except Exception:
|
||||
# .get retrieves a partial object
|
||||
if item.type == 'episode':
|
||||
show_name = item.grandparentTitle
|
||||
ep_name = item.title
|
||||
title = "{} {}".format(show_name, ep_name)
|
||||
show = sectionTo.get(show_name)
|
||||
watch_check = show.episode(season=item.parentIndex, episode=item.index)
|
||||
else:
|
||||
title = item.title
|
||||
watch_check = sectionTo.get(title)
|
||||
# .fetchItem retrieves a full object
|
||||
fetch_check = sectionTo.fetchItem(watch_check.key)
|
||||
# If item is already watched ignore
|
||||
if not fetch_check.isWatched:
|
||||
# todo-me should watched count be synced?
|
||||
fetch_check.markWatched()
|
||||
print("Synced watched status of {} to account {}...".format(title, userTo))
|
||||
|
||||
except Exception as e:
|
||||
print(e)
|
||||
pass
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
parser = argparse.ArgumentParser(description="Sync watch status from one user to others.",
|
||||
formatter_class=argparse.RawTextHelpFormatter)
|
||||
requiredNamed = parser.add_argument_group('required named arguments')
|
||||
parser.add_argument('--libraries', nargs='*', choices=sections_lst, metavar='library',
|
||||
help='Space separated list of case sensitive names to process. Allowed names are: \n'
|
||||
'(choices: %(choices)s)')
|
||||
parser.add_argument('--allLibraries', action='store_true',
|
||||
help='Select all libraries.')
|
||||
parser.add_argument('--ratingKey', nargs=1,
|
||||
parser.add_argument('--libraries', nargs='*', metavar='library',
|
||||
help='Libraries to scan for watched content.')
|
||||
parser.add_argument('--ratingKey', nargs="?", type=str,
|
||||
help='Rating key of item whose watch status is to be synced.')
|
||||
requiredNamed = parser.add_argument_group('required named arguments')
|
||||
requiredNamed.add_argument('--userFrom', metavar='user=server', required=True,
|
||||
type=lambda kv: kv.split("="),
|
||||
type=lambda kv: kv.split("="), default=["", ""],
|
||||
help='Select user and server to sync from')
|
||||
requiredNamed.add_argument('--userTo', nargs='*', metavar='user=server', required=True,
|
||||
type=lambda kv: kv.split("="),
|
||||
help='Select user and server to sync to.')
|
||||
|
||||
|
||||
opts = parser.parse_args()
|
||||
|
||||
# print(opts)
|
||||
tautulli_server = ''
|
||||
|
||||
libraries = []
|
||||
all_sections = {}
|
||||
watchedFrom = ''
|
||||
count = 25
|
||||
start = 0
|
||||
plex_admin = Plex(PLEX_TOKEN)
|
||||
|
||||
userFrom, serverFrom = opts.userFrom
|
||||
|
||||
if serverFrom == "Tautulli":
|
||||
# Create a Tautulli instance
|
||||
tautulli_server = Tautulli(Connection(url=TAUTULLI_URL.rstrip('/'),
|
||||
apikey=TAUTULLI_APIKEY,
|
||||
verify_ssl=VERIFY_SSL))
|
||||
|
||||
if serverFrom == "Tautulli" and opts.libraries:
|
||||
_sections = {}
|
||||
# Pull all libraries from Tautulli
|
||||
tautulli_sections = tautulli_server.get_libraries()
|
||||
for section in tautulli_sections:
|
||||
section_obj = Library(section)
|
||||
_sections[section_obj.title] = section_obj
|
||||
all_sections[serverFrom] = _sections
|
||||
elif serverFrom != "Tautulli" and opts.libraries:
|
||||
all_sections = plex_admin.all_sections()
|
||||
|
||||
# Defining libraries
|
||||
libraries = ''
|
||||
if opts.allLibraries and not opts.libraries:
|
||||
libraries = sections_lst
|
||||
elif not opts.allLibraries and opts.libraries:
|
||||
libraries = opts.libraries
|
||||
elif opts.allLibraries and opts.libraries:
|
||||
# If allLibraries is used then any libraries listed will be excluded
|
||||
if opts.libraries:
|
||||
for library in opts.libraries:
|
||||
sections_lst.remove(library)
|
||||
libraries = sections_lst
|
||||
|
||||
# Create Sync-From user account
|
||||
plexFrom = get_account(opts.userFrom[0], opts.userFrom[1])
|
||||
|
||||
# Go through list of users
|
||||
for user in opts.userTo:
|
||||
plexTo = get_account(user[0], user[1])
|
||||
if libraries:
|
||||
# Go through Libraries
|
||||
for library in libraries:
|
||||
try:
|
||||
print('Checking library: {}'.format(library))
|
||||
# Check library for watched items
|
||||
section = plexFrom.library.section(library)
|
||||
mark_watached(section, plexTo, user[0])
|
||||
except Exception as e:
|
||||
if str(e).startswith('Unknown'):
|
||||
print('Library ({}) does not have a watch status.'.format(library))
|
||||
elif str(e).startswith('(404)'):
|
||||
print('Library ({}) not shared to user: {}.'.format(library, user))
|
||||
else:
|
||||
print(e)
|
||||
pass
|
||||
# Check rating key from Tautulli
|
||||
elif opts.ratingKey:
|
||||
for key in opts.ratingKey:
|
||||
item = plexTo.fetchItem(int(key))
|
||||
title = item.title.encode('utf-8')
|
||||
print('Syncing watch status of {} to {}\'s account.'.format(title, user[0]))
|
||||
item.markWatched()
|
||||
else:
|
||||
print('No libraries or rating key provided.')
|
||||
if all_sections.get(serverFrom):
|
||||
if all_sections.get(serverFrom).get(library):
|
||||
libraries.append(all_sections.get(serverFrom).get(library))
|
||||
else:
|
||||
print("No matching library name '{}'".format(library))
|
||||
exit()
|
||||
|
||||
else:
|
||||
print("No matching server name '{}'".format(serverFrom))
|
||||
exit()
|
||||
|
||||
# If userFrom is Plex Admin
|
||||
# if userFrom == plex_admin.account.title and serverFrom != "Tautulli" and opts.libraries:
|
||||
# resource = plex_admin.admin_servers().get(serverFrom)
|
||||
# print('Connecting {} to {}...'.format(userFrom, serverFrom))
|
||||
# server_connection = resource.connect()
|
||||
# baseurl = server_connection._baseurl.split('.')
|
||||
# url = ''.join([baseurl[0].replace('-', '.'),
|
||||
# baseurl[-1].replace('direct', '')])
|
||||
#
|
||||
# token = PLEX_TOKEN
|
||||
# admin_connection = Plex(url=url, token=token)
|
||||
# watchedFrom = admin_connection.server
|
||||
if serverFrom != "Tautulli" and opts.libraries:
|
||||
watchedFrom = check_users_access(userFrom, serverFrom, libraries)
|
||||
|
||||
if libraries:
|
||||
print("Finding watched items in libraries...")
|
||||
plexTo = []
|
||||
|
||||
for user, server_name in opts.userTo:
|
||||
plexTo.append([user, check_users_access(user, server_name, libraries)])
|
||||
|
||||
for _library in libraries:
|
||||
watched_lst = []
|
||||
print("Checking {}'s library: '{}' watch statuses...".format(userFrom, _library.title))
|
||||
if tautulli_server:
|
||||
while True:
|
||||
# Getting all watched history for userFrom
|
||||
tt_watched = tautulli_server.get_watched_history(userFrom, _library.key, start, count)
|
||||
if all([tt_watched]):
|
||||
start += count
|
||||
for item in tt_watched:
|
||||
watched_lst.append(Metadata(item))
|
||||
continue
|
||||
elif not all([tt_watched]):
|
||||
break
|
||||
start += count
|
||||
else:
|
||||
# Check library for watched items
|
||||
sectionFrom = watchedFrom.library.section(_library.title)
|
||||
if _library.type == 'show':
|
||||
for episode in sectionFrom.searchEpisodes(unwatched=False):
|
||||
watched_lst.append(episode)
|
||||
else:
|
||||
for item in sectionFrom.search(unwatched=False):
|
||||
watched_lst.append(item)
|
||||
|
||||
for user in plexTo:
|
||||
username, server = user
|
||||
sync_watch_status(watched_lst, _library.title, server, username)
|
||||
|
||||
elif opts.ratingKey and userFrom == "Tautulli" and serverFrom == "Tautulli":
|
||||
print('Request from Tautulli notification agent to update watch status')
|
||||
plexTo = []
|
||||
|
||||
for user, server_name in opts.userTo:
|
||||
# Check access and connect
|
||||
plexTo.append([user, check_users_access(user, server_name, libraries)])
|
||||
|
||||
for user in plexTo:
|
||||
username, server = user
|
||||
item = Metadata(tautulli_server.get_metadata(opts.ratingKey))
|
||||
sync_watch_status([item], item.libraryName, server, username)
|
||||
|
||||
else:
|
||||
print("You aren't using this script correctly... bye!")
|
Loading…
Reference in New Issue
Block a user