diff --git a/reporting/plex_netflix_check.py b/reporting/plex_netflix_check.py deleted file mode 100644 index 9438e9f..0000000 --- a/reporting/plex_netflix_check.py +++ /dev/null @@ -1,252 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -""" -usage: plex_netflix_check.py [-h] [-l [...]] [-s ] [-t ] - -Use instantwatcher.com to find if Plex items are on Netflix, Amazon, or both. - -optional arguments: - -h, --help show this help message and exit - -l [ ...], --library [ ...] - Space separated list of case sensitive names to process. Allowed names are: - (choices: Your show or movie library names) - -s [], --search [] Search any name. - -t [], --type [] Refine search for name by using type. - (choices: movie, show) - -e [], --episodes [] Refine search for individual episodes. - (choices: True, False) - (default: False) - -site [], --site [] Refine search for name by using type. - (choices: Netflix, Amazon, Both) - (default: Both) - -sl [], --search_limit [] - Define number of search returns from page. Zero returns all. - (default: 5) - -If title is matched in both, Amazon is first then Netflix. -""" -from __future__ import print_function -from __future__ import unicode_literals - -from builtins import str -import requests -import argparse -from xmljson import badgerfish as bf -from lxml.html import fromstring -from time import sleep -from plexapi.server import PlexServer, CONFIG -# pip install plexapi - - -# ## Edit ## -PLEX_URL = '' -PLEX_TOKEN = '' - -if not PLEX_URL: - PLEX_URL = CONFIG.data['auth'].get('server_baseurl', '') - -if not PLEX_TOKEN: - PLEX_TOKEN = CONFIG.data['auth'].get('server_token', '') - -# ## /Edit ## - -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) - -plex = PlexServer(PLEX_URL, PLEX_TOKEN, session=sess) - - -def instantwatch_search(name, media_type, site, search_limit): - - NETFLIX_URL = 'http://www.netflix.com/title/' - limit = False - results_count = 0 - - if media_type == 'movie': - content_type = '1' - elif media_type == 'show': - content_type = '2' - elif media_type == 'episode': - content_type = '4' - else: - content_type = '' - - payload = {'content_type': content_type, - 'q': name.lower()} - - if site == 'Netflix': - r = requests.get('http://instantwatcher.com/netflix/78/search'.rstrip('/'), params=payload) - elif site == 'Amazon': - r = requests.get('http://instantwatcher.com/amazon/search'.rstrip('/'), params=payload) - else: - r = requests.get('http://instantwatcher.com/u/search'.rstrip('/'), params=payload) - - if r.status_code != 200: - print('{} not found: {}'.format(name, r.url)) - return 0 - results_lst = [] - res_data = bf.data(fromstring(r.content)) - - res_data = res_data['html']['body']['div']['div'][1] - - # Any matches? - res_results = res_data['div'][1]['div'][0] - title_check = res_data['div'][1]['div'][1] - - try: - if res_results['span']: - total_results = res_results['span'] - for data in total_results: - results_lst += [data['$']] - except Exception: - pass - - print('{} found {}.'.format(results_lst[0], results_lst[1])) - result_count = int(results_lst[1].split(' ')[0]) - - amazon_id = '' - amazon_url = '' - - # Title match - if result_count == 0: - print('0 matches, moving on.') - pass - else: - item_results_page = title_check['div']['div'] - if result_count > 1: - for results in item_results_page: - for data in results['a']: - try: - amazon_id = data['@data-amazon-title-id'] - amazon_url = data['@data-amazon-uri'] - except Exception: - pass - - for data in results['span']: - if data['@class'] == 'title' and search_limit != 0: - if str(data['a']['$']).lower().startswith(name.lower()): - if amazon_id: - if data['a']['@data-title-id'] == amazon_id: - print('Match found on Amazon for {}'.format(data['a']['$'])) - print('Page: {}'.format(amazon_url)) - else: - print('Match found on Netflix for {}'.format(data['a']['$'])) - print('Page: {}{}'.format(NETFLIX_URL, data['a']['@data-title-id'])) - results_count += 1 - search_limit -= 1 - if search_limit == 0: - limit = True - - elif data['@class'] == 'title' and search_limit == 0 and limit is False: - if data['a']['$'].lower().startswith(name.lower()): - if amazon_id: - if data['a']['@data-title-id'] == amazon_id: - print('Match found on Amazon for {}'.format(data['a']['$'])) - print('Page: {}'.format(amazon_url)) - else: - print('Match found on Netflix for {}'.format(data['a']['$'])) - print('Page: {}{}'.format(NETFLIX_URL, data['a']['@data-title-id'])) - results_count += 1 - - elif result_count == 1: - for data in item_results_page['a']: - try: - amazon_id = data['@data-amazon-title-id'] - amazon_url = data['@data-amazon-uri'] - except Exception: - pass - for data in item_results_page['span']: - if data['@class'] == 'title': - if data['a']['$'].lower().startswith(name.lower()): - print('Match! For {}'.format(data['a']['$'])) - if amazon_id: - if data['a']['@data-title-id'] == amazon_id: - print('Page: {}'.format(amazon_url)) - else: - print('Page: {}{}'.format(NETFLIX_URL, data['a']['@data-title-id'])) - results_count += 1 - else: - print('Could not find exact name match.') - return results_count - - -def plex_library_search(lib_name, site, epi_search, search_limit): - for title in plex.library.section(lib_name).all(): - print('Running check on {}'.format(title.title)) - file_path = [] - if title.type == 'show' and epi_search is True: - if instantwatch_search(title.title, title.type, site, search_limit) > 0: - print('Show was found. Searching for episode paths.') - for episode in title.episodes(): - # Need to check episodes against sites to truly find episode matches. - # For now just return paths for episodes if Show name matches. - # print('Running check on {} - {}'.format(title.title, episode.title)) - # show_ep = '{} - {}'.format(title.title, episode.title) - # if instantwatch_search(show_ep, 'episode', site) > 0: - file_path += [episode.media[0].parts[0].file] - - elif title.type == 'movie': - if instantwatch_search(title.title, title.type, site, search_limit) > 0: - file_path = title.media[0].parts[0].file - else: - if instantwatch_search(title.title, title.type, site, search_limit) > 0: - print('Show was found but path is not defined.') - - if file_path: - if type(file_path) is str: - print('File: {}'.format(file_path)) - elif type(file_path) is list: - print('Files: \n{}'.format(' \n'.join(file_path))) - - print('Waiting 5 seconds before next search.') - sleep(5) - - -def main(): - - sections_lst = [d.title for d in plex.library.sections() if d.type in ['show', 'movie']] - - parser = argparse.ArgumentParser(description="Use instantwatcher.com to find if Plex items are on Netflix.", - formatter_class=argparse.RawTextHelpFormatter) - parser.add_argument('-l', '--library', metavar='', choices=sections_lst, nargs='+', - help='Space separated list of case sensitive names to process. Allowed names are:\n' - '(choices: %(choices)s)') - parser.add_argument('-s', '--search', metavar='', nargs='?', type=str, - help='Search any name.') - parser.add_argument('-m', '--media_type', metavar='', choices=['movie', 'show'], nargs='?', - help='Refine search for name by using media type.\n' - '(choices: %(choices)s)') - parser.add_argument('-e', '--episodes', metavar='', nargs='?', type=bool, default=False, choices=[True, False], - help='Refine search for individual episodes.\n' - '(choices: %(choices)s)\n(default: %(default)s)') - parser.add_argument('-site', '--site', metavar='', choices=['Netflix', 'Amazon', 'Both'], nargs='?', - default='Netflix', help='Refine search for name by using type.\n' - '(choices: %(choices)s)\n(default: %(default)s)') - parser.add_argument('-sl', '--search_limit', metavar='', nargs='?', type=int, default=5, - help='Define number of search returns from page. Zero returns all.' - '\n(default: %(default)s)') - - opts = parser.parse_args() - # print(opts) - - if opts.search: - instantwatch_search(opts.search, opts.media_type, opts.site, opts.search_limit) - else: - if len(opts.library) > 1: - for section in opts.library: - plex_library_search(section, opts.site, opts.episodes, opts.search_limit) - else: - plex_library_search(opts.library[0], opts.site, opts.episodes, opts.search_limit) - - -if __name__ == '__main__': - main() diff --git a/reporting/streaming_service_availability.py b/reporting/streaming_service_availability.py new file mode 100644 index 0000000..a291681 --- /dev/null +++ b/reporting/streaming_service_availability.py @@ -0,0 +1,100 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# Description: Check media availability on streaming services. +# Author: /u/SwiftPanda16 +# Requires: plexapi + +import argparse +import os +from plexapi import CONFIG +from plexapi.server import PlexServer +from plexapi.exceptions import BadRequest + +PLEX_URL = '' +PLEX_TOKEN = '' + +# Environment Variables or PlexAPI Config +PLEX_URL = os.getenv('PLEX_URL', PLEX_URL) or CONFIG.data['auth'].get('server_baseurl') +PLEX_TOKEN = os.getenv('PLEX_TOKEN', PLEX_TOKEN) or CONFIG.data['auth'].get('server_token') + + +def check_streaming_services(plex, libraries, services, available_only): + if libraries: + sections = [plex.library.section(library) for library in libraries] + else: + sections = [ + section for section in plex.library.sections() + if section.agent in {'tv.plex.agents.movie', 'tv.plex.agents.series'} + ] + + for section in sections: + print(f'{section.title}') + + for item in section.all(): + try: + availabilities = item.streamingServices() + except BadRequest: + continue + + if services: + availabilities = [ + availability for availability in availabilities + if availability.title in services + ] + + if available_only and not availabilities: + continue + + if item.type == 'movie': + subtitle = item.media[0].videoResolution + subtitle = subtitle.upper() if subtitle == 'sd' else ((subtitle + 'p') if subtitle.isdigit() else '') + else: + subtitle = item.childCount + subtitle = str(subtitle) + ' season' + ('s' if subtitle > 1 else '') + + print(f' └─ {item.title} ({item.year}) ({subtitle})') + + for availability in availabilities: + title = availability.title + quality = availability.quality + offerType = availability.offerType.capitalize() + priceDescription = (' ' + availability.priceDescription) if availability.priceDescription else '' + print(f' └─ {title} ({quality} - {offerType}{priceDescription})') + + print() + + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument( + '--libraries', + '-l', + nargs='+', + help=( + 'Plex libraries to check (e.g. Movies, TV Shows, etc.). ' + 'Default: All movie and tv show libraries using the Plex Movie or Plex TV Series agents.' + ) + ) + parser.add_argument( + '--services', + '-s', + nargs='+', + help=( + 'Streaming services to check (e.g. Netflix, Disney+, Amazon Prime Video, etc.). ' + 'Note: Must be the exact name of the service as it appears in Plex. ' + 'Default: All services.' + ) + ) + parser.add_argument( + '--available_only', + '-a', + action='store_true', + help=( + 'Only list media that is available on at least one streaming service.' + ) + ) + opts = parser.parse_args() + + plex = PlexServer(PLEX_URL, PLEX_TOKEN) + check_streaming_services(plex, **vars(opts))