Merge pull request #270 from blacktwin/last_played
Updating media_manager
This commit is contained in:
commit
4a67ece43d
@ -33,6 +33,7 @@ import re
|
|||||||
from collections import Counter
|
from collections import Counter
|
||||||
from plexapi.server import PlexServer
|
from plexapi.server import PlexServer
|
||||||
from plexapi.server import CONFIG
|
from plexapi.server import CONFIG
|
||||||
|
from plexapi.exceptions import NotFound
|
||||||
from requests import Session
|
from requests import Session
|
||||||
from requests.adapters import HTTPAdapter
|
from requests.adapters import HTTPAdapter
|
||||||
from requests.exceptions import RequestException
|
from requests.exceptions import RequestException
|
||||||
@ -54,7 +55,7 @@ if not TAUTULLI_APIKEY:
|
|||||||
|
|
||||||
VERIFY_SSL = False
|
VERIFY_SSL = False
|
||||||
|
|
||||||
SELECTOR = ['watched', 'unwatched', 'transcoded', 'rating', 'size']
|
SELECTOR = ['watched', 'unwatched', 'transcoded', 'rating', 'size', 'lastPlayed']
|
||||||
ACTIONS = ['delete', 'move', 'archive', 'optimize', 'show']
|
ACTIONS = ['delete', 'move', 'archive', 'optimize', 'show']
|
||||||
OPERATORS = { '>': lambda v, q: v > q,
|
OPERATORS = { '>': lambda v, q: v > q,
|
||||||
'>=': lambda v, q: v >= q,
|
'>=': lambda v, q: v >= q,
|
||||||
@ -231,7 +232,8 @@ class Tautulli(object):
|
|||||||
payload = {}
|
payload = {}
|
||||||
return self._call_api('get_libraries', payload)
|
return self._call_api('get_libraries', payload)
|
||||||
|
|
||||||
def get_library_media_info(self, section_id, start, length, unwatched=None, date=None, order_column=None):
|
def get_library_media_info(self, section_id, start, length, unwatched=None, date=None, order_column=None,
|
||||||
|
last_played=None):
|
||||||
"""Call Tautulli's get_library_media_info api endpoint."""
|
"""Call Tautulli's get_library_media_info api endpoint."""
|
||||||
payload = {'section_id': section_id}
|
payload = {'section_id': section_id}
|
||||||
if start:
|
if start:
|
||||||
@ -248,6 +250,8 @@ class Tautulli(object):
|
|||||||
elif unwatched and date:
|
elif unwatched and date:
|
||||||
return [d for d in library_stats['data'] if d['play_count'] is None
|
return [d for d in library_stats['data'] if d['play_count'] is None
|
||||||
and (float(d['added_at'])) < date]
|
and (float(d['added_at'])) < date]
|
||||||
|
elif last_played and date:
|
||||||
|
return [d for d in library_stats['data'] if d['play_count'] is not None]
|
||||||
else:
|
else:
|
||||||
return [d for d in library_stats['data']]
|
return [d for d in library_stats['data']]
|
||||||
|
|
||||||
@ -298,12 +302,17 @@ def plex_deletion(items, libraries, toggleDeletion):
|
|||||||
|
|
||||||
print("The following items were added before {} and marked for deletion.".format(opts.date))
|
print("The following items were added before {} and marked for deletion.".format(opts.date))
|
||||||
for item in items:
|
for item in items:
|
||||||
if isinstance(item, int):
|
try:
|
||||||
plex_item = plex.fetchItem(item)
|
if isinstance(item, int):
|
||||||
else:
|
plex_item = plex.fetchItem(item)
|
||||||
plex_item = plex.fetchItem(int(item.rating_key))
|
elif isinstance(item, str):
|
||||||
plex_item.delete()
|
plex_item = plex.fetchItem(int(item))
|
||||||
print("Item: {} was deleted".format(plex_item.title))
|
else:
|
||||||
|
plex_item = plex.fetchItem(int(item.rating_key))
|
||||||
|
plex_item.delete()
|
||||||
|
print("Item: {} was deleted".format(plex_item.title))
|
||||||
|
except NotFound:
|
||||||
|
print("Item: {} may already have been deleted.".format(item))
|
||||||
for _library in libraries:
|
for _library in libraries:
|
||||||
section = plex.library.sectionByID(_library.key)
|
section = plex.library.sectionByID(_library.key)
|
||||||
print("Emptying Trash from library {}".format(_library.title))
|
print("Emptying Trash from library {}".format(_library.title))
|
||||||
@ -313,6 +322,42 @@ def plex_deletion(items, libraries, toggleDeletion):
|
|||||||
plex._allowMediaDeletion(False)
|
plex._allowMediaDeletion(False)
|
||||||
|
|
||||||
|
|
||||||
|
def last_played_work(sectionID, date=None):
|
||||||
|
"""
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
sectionID (int): Library key
|
||||||
|
date (float): Epoch time
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
last_played_lst (list): List of Metdata objects of last played items
|
||||||
|
"""
|
||||||
|
count = 25
|
||||||
|
start = 0
|
||||||
|
last_played_lst = []
|
||||||
|
while True:
|
||||||
|
|
||||||
|
# Getting all watched history
|
||||||
|
tt_history = tautulli_server.get_library_media_info(section_id=sectionID,
|
||||||
|
start=start, length=count, last_played=True,
|
||||||
|
date=date, order_column='last_played')
|
||||||
|
|
||||||
|
if all([tt_history]):
|
||||||
|
start += count
|
||||||
|
for item in tt_history:
|
||||||
|
_meta = tautulli_server.get_metadata(item['rating_key'])
|
||||||
|
metadata = Metadata(_meta)
|
||||||
|
if (float(item['last_played'])) < date:
|
||||||
|
metadata.last_played = item['last_played']
|
||||||
|
last_played_lst.append(metadata)
|
||||||
|
elif not all([tt_history]):
|
||||||
|
break
|
||||||
|
start += count
|
||||||
|
|
||||||
|
return last_played_lst
|
||||||
|
|
||||||
|
|
||||||
def unwatched_work(sectionID, date=None):
|
def unwatched_work(sectionID, date=None):
|
||||||
"""
|
"""
|
||||||
Parameters
|
Parameters
|
||||||
@ -422,6 +467,8 @@ def watched_work(user, sectionID=None, ratingKey=None):
|
|||||||
if user.watch.get(metadata.rating_key):
|
if user.watch.get(metadata.rating_key):
|
||||||
user.watch.get(metadata.rating_key).watched_status += 1
|
user.watch.get(metadata.rating_key).watched_status += 1
|
||||||
else:
|
else:
|
||||||
|
_meta = tautulli_server.get_metadata(metadata.rating_key)
|
||||||
|
metadata = Metadata(_meta)
|
||||||
user.watch.update({metadata.rating_key: metadata})
|
user.watch.update({metadata.rating_key: metadata})
|
||||||
|
|
||||||
continue
|
continue
|
||||||
@ -479,6 +526,46 @@ def transcode_work(sectionID, operator, value):
|
|||||||
return transcoding_lst
|
return transcoding_lst
|
||||||
|
|
||||||
|
|
||||||
|
def action_show(items, selector, date, users=None):
|
||||||
|
sizes = []
|
||||||
|
|
||||||
|
print("{} item(s) have been found.".format(len(items)))
|
||||||
|
if selector == 'lastPlayed':
|
||||||
|
print("The following items were last played before {}".format(date))
|
||||||
|
elif selector == 'watched':
|
||||||
|
print("The following items were watched by {}".format(", ".join([user.name for user in users])))
|
||||||
|
elif selector == 'unwatched':
|
||||||
|
print("The following items were added before {} and are unwatched".format(date))
|
||||||
|
else:
|
||||||
|
print("The following items were added before {}".format(date))
|
||||||
|
|
||||||
|
for item in items:
|
||||||
|
try:
|
||||||
|
if selector == 'watched':
|
||||||
|
item = users[0].watch[item]
|
||||||
|
added_at = datetime.datetime.utcfromtimestamp(float(item.added_at)).strftime("%Y-%m-%d")
|
||||||
|
size = int(item.file_size) if item.file_size else 0
|
||||||
|
sizes.append(size)
|
||||||
|
|
||||||
|
if selector == 'lastPlayed':
|
||||||
|
last_played = datetime.datetime.utcfromtimestamp(float(item.last_played)).strftime("%Y-%m-%d")
|
||||||
|
print(u"\t{} added {} and last played {}\tSize: {}\n\t\tFile: {}".format(
|
||||||
|
item.title, added_at, last_played, sizeof_fmt(size), item.file))
|
||||||
|
|
||||||
|
elif selector == 'transcoded':
|
||||||
|
print(u"\t{} added {}\tSize: {}\tTransocded: {} time(s)\n\t\tFile: {}".format(
|
||||||
|
item.title, added_at, sizeof_fmt(size), item.transcode_count, item.file))
|
||||||
|
|
||||||
|
else:
|
||||||
|
print(u"\t{} added {}\tSize: {}\n\t\tFile: {}".format(
|
||||||
|
item.title, added_at, sizeof_fmt(size), item.file))
|
||||||
|
|
||||||
|
except TypeError as e:
|
||||||
|
print("Item: {} caused the following error: {}".format(item.rating_key, e))
|
||||||
|
|
||||||
|
total_size = sum(sizes)
|
||||||
|
print("Total size: {}".format(sizeof_fmt(total_size)))
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|
||||||
session = Connection().session
|
session = Connection().session
|
||||||
@ -541,15 +628,25 @@ if __name__ == '__main__':
|
|||||||
all_sections = []
|
all_sections = []
|
||||||
watched_lst = []
|
watched_lst = []
|
||||||
unwatched_lst = []
|
unwatched_lst = []
|
||||||
|
last_played_lst = []
|
||||||
size_lst = []
|
size_lst = []
|
||||||
user_lst = []
|
user_lst = []
|
||||||
transcode_lst = []
|
transcode_lst = []
|
||||||
|
date_format = ''
|
||||||
|
|
||||||
if opts.date:
|
# Check for days or date format
|
||||||
date = time.mktime(time.strptime(opts.date, "%Y-%m-%d"))
|
if opts.date and opts.date.isdigit():
|
||||||
else:
|
days = datetime.date.today() - datetime.timedelta(int(opts.date))
|
||||||
|
date = time.mktime(days.timetuple())
|
||||||
|
elif opts.date is None:
|
||||||
date = None
|
date = None
|
||||||
|
else:
|
||||||
|
date = time.mktime(time.strptime(opts.date, "%Y-%m-%d"))
|
||||||
|
|
||||||
|
if date:
|
||||||
|
days = (datetime.datetime.utcnow() - datetime.datetime.fromtimestamp(date))
|
||||||
|
date_format = time.strftime("%Y-%m-%d", time.localtime(date))
|
||||||
|
date_format = '{} ({} days)'.format(date_format, days.days)
|
||||||
# Create a Tautulli instance
|
# Create a Tautulli instance
|
||||||
tautulli_server = Tautulli(Connection(url=TAUTULLI_URL.rstrip("/"),
|
tautulli_server = Tautulli(Connection(url=TAUTULLI_URL.rstrip("/"),
|
||||||
apikey=TAUTULLI_APIKEY,
|
apikey=TAUTULLI_APIKEY,
|
||||||
@ -583,16 +680,7 @@ if __name__ == '__main__':
|
|||||||
unwatched_lst += unwatched_work(sectionID=_library.key, date=date)
|
unwatched_lst += unwatched_work(sectionID=_library.key, date=date)
|
||||||
|
|
||||||
if opts.action == "show":
|
if opts.action == "show":
|
||||||
print("The following items were added before {}".format(opts.date))
|
action_show(unwatched_lst, opts.select, date_format)
|
||||||
sizes = []
|
|
||||||
for item in unwatched_lst:
|
|
||||||
added_at = datetime.datetime.utcfromtimestamp(float(item.added_at)).strftime("%Y-%m-%d")
|
|
||||||
size = int(item.file_size) if item.file_size else ''
|
|
||||||
sizes.append(size)
|
|
||||||
print(u"\t{} added {}\tSize: {}\n\t\tFile: {}".format(
|
|
||||||
item.title, added_at, sizeof_fmt(size), item.file))
|
|
||||||
total_size = sum(sizes)
|
|
||||||
print("Total size: {}".format(sizeof_fmt(total_size)))
|
|
||||||
|
|
||||||
if opts.action == "delete":
|
if opts.action == "delete":
|
||||||
plex_deletion(unwatched_lst, libraries, opts.toggleDeletion)
|
plex_deletion(unwatched_lst, libraries, opts.toggleDeletion)
|
||||||
@ -600,7 +688,7 @@ if __name__ == '__main__':
|
|||||||
if opts.select == "watched":
|
if opts.select == "watched":
|
||||||
if libraries:
|
if libraries:
|
||||||
for user in user_lst:
|
for user in user_lst:
|
||||||
print(("Finding watched items from user: {}",format(user.name)))
|
print("Finding watched items from user: {}".format(user.name))
|
||||||
for _library in libraries:
|
for _library in libraries:
|
||||||
print("Checking library: '{}' watch statuses...".format(_library.title))
|
print("Checking library: '{}' watch statuses...".format(_library.title))
|
||||||
watched_work(user=user, sectionID=_library.key)
|
watched_work(user=user, sectionID=_library.key)
|
||||||
@ -619,19 +707,28 @@ if __name__ == '__main__':
|
|||||||
watched_work(user=user, ratingKey=opts.ratingKey)
|
watched_work(user=user, ratingKey=opts.ratingKey)
|
||||||
|
|
||||||
# Find all items watched by all users
|
# Find all items watched by all users
|
||||||
all_watched = [key for user in user_lst for key in user.watch.keys()]
|
all_watched = [key for user in user_lst for key in user.watch.keys() if key is not None]
|
||||||
counts = Counter(all_watched)
|
counts = Counter(all_watched)
|
||||||
watched_by_all = [id for id in all_watched if counts[id] >= len(user_lst)]
|
watched_by_all = [id for id in all_watched if counts[id] >= len(user_lst)]
|
||||||
watched_by_all = list(set(watched_by_all))
|
watched_by_all = list(set(watched_by_all))
|
||||||
|
|
||||||
if opts.action == "show":
|
if opts.action == "show":
|
||||||
print("The following items were watched by {}".format(", ".join([user.name for user in user_lst])))
|
action_show(watched_by_all, opts.select, date_format, user_lst)
|
||||||
for watched in watched_by_all:
|
|
||||||
metadata = user_lst[0].watch[watched]
|
|
||||||
print(u" {}".format(metadata.full_title))
|
|
||||||
|
|
||||||
if opts.action == "delete":
|
if opts.action == "delete":
|
||||||
plex_deletion(watched_by_all, libraries, opts.toggleDeletion)
|
plex_deletion(watched_by_all, libraries, opts.toggleDeletion)
|
||||||
|
|
||||||
|
if opts.select == "lastPlayed":
|
||||||
|
if libraries:
|
||||||
|
for _library in libraries:
|
||||||
|
print("Checking library: '{}' watch statuses...".format(_library.title))
|
||||||
|
last_played_lst += last_played_work(sectionID=_library.key, date=date)
|
||||||
|
|
||||||
|
if opts.action == "show":
|
||||||
|
action_show(last_played_lst, opts.select, date_format)
|
||||||
|
|
||||||
|
if opts.action == "delete":
|
||||||
|
plex_deletion(last_played_lst, libraries, opts.toggleDeletion)
|
||||||
|
|
||||||
if opts.select in ["size", "rating", "transcoded"]:
|
if opts.select in ["size", "rating", "transcoded"]:
|
||||||
if opts.selectValue:
|
if opts.selectValue:
|
||||||
@ -654,15 +751,7 @@ if __name__ == '__main__':
|
|||||||
size_lst += size_work(sectionID=_library.key, operator=op, value=size, episodes=opts.episodes)
|
size_lst += size_work(sectionID=_library.key, operator=op, value=size, episodes=opts.episodes)
|
||||||
|
|
||||||
if opts.action == "show":
|
if opts.action == "show":
|
||||||
sizes = []
|
action_show(size_lst, opts.select, opts.date)
|
||||||
for item in size_lst:
|
|
||||||
added_at = datetime.datetime.utcfromtimestamp(float(item.added_at)).strftime("%Y-%m-%d")
|
|
||||||
size = int(item.file_size) if item.file_size else 0
|
|
||||||
sizes.append(size)
|
|
||||||
print(u"\t{} added {}\tSize: {}\n\t\tFile: {}".format(
|
|
||||||
item.title, added_at, sizeof_fmt(size), item.file))
|
|
||||||
total_size = sum(sizes)
|
|
||||||
print("Total size: {}".format(sizeof_fmt(total_size)))
|
|
||||||
else:
|
else:
|
||||||
print("Size must end with one of these notations: {}".format(", ".join(UNTIS.keys())))
|
print("Size must end with one of these notations: {}".format(", ".join(UNTIS.keys())))
|
||||||
pass
|
pass
|
||||||
@ -677,10 +766,5 @@ if __name__ == '__main__':
|
|||||||
transcode_lst += transcoded_lst
|
transcode_lst += transcoded_lst
|
||||||
|
|
||||||
if opts.action == "show":
|
if opts.action == "show":
|
||||||
print("{} item(s) have been found.".format(len(transcode_lst)))
|
action_show(transcode_lst, opts.select, date_format)
|
||||||
for item in transcode_lst:
|
|
||||||
added_at = datetime.datetime.utcfromtimestamp(float(item.added_at)).strftime("%Y-%m-%d")
|
|
||||||
size = int(item.file_size) if item.file_size else 0
|
|
||||||
file_size = sizeof_fmt(size)
|
|
||||||
print(u"\t{} added {}\tSize: {}\tTransocded: {} time(s)\n\t\tFile: {}".format(
|
|
||||||
item.title, added_at, file_size, item.transcode_count, item.file))
|
|
||||||
|
Loading…
Reference in New Issue
Block a user