Advertisement
Guest User

Untitled

a guest
Dec 5th, 2017
124
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 5.43 KB | None | 0 0
  1. import re, sys, time, getpass, logging, threading
  2. import plexapi.utils
  3. from tqdm import tqdm
  4. from retry import retry
  5. from pytvdbapi import api
  6. from pytvdbapi.error import TVDBIndexError
  7. from plexapi.myplex import MyPlexAccount
  8. from plexapi.exceptions import BadRequest
  9. from imdb import IMDb, IMDbDataAccessError
  10. from http.client import RemoteDisconnected, ResponseNotReady
  11.  
  12. class Plex():
  13.     def __init__(self):
  14.         self.account = self.get_account()
  15.         self.server = self.get_account_server(self.account)
  16.         self.section = self.get_server_section(self.server)
  17.         self.media = self.get_flat_media(self.section)
  18.  
  19.     @retry(BadRequest)
  20.     def get_account(self):
  21.         username = input("Plex Username: ")
  22.         password = getpass.getpass()
  23.  
  24.         return MyPlexAccount(username, password)
  25.    
  26.     def get_account_server(self, account):
  27.         servers = [ _ for _ in account.resources() if _.product == 'Plex Media Server' ]
  28.         if not servers:
  29.             print('No available servers.')
  30.             sys.exit()
  31.  
  32.         return plexapi.utils.choose('Select server index', servers, 'name').connect()
  33.  
  34.     def get_server_section(self, server):
  35.         sections = [ _ for _ in server.library.sections() if _.type in {'movie', 'show'} ]
  36.         if not sections:
  37.             print('No available sections.')
  38.             sys.exit()
  39.  
  40.         return plexapi.utils.choose('Select section index', sections, 'title')
  41.  
  42.     def get_flat_media(self, section):
  43.         # Movie sections are already flat
  44.         if section.type == 'movie':
  45.             return self.section.all()
  46.         else:
  47.             episodes = []
  48.             for show in self.section.all():
  49.                 episodes += show.episodes()
  50.             return episodes
  51.  
  52.     def create_playlist(self, name, media):
  53.         playlist = next((p for p in self.server.playlists() if p.title == name), None)
  54.         if playlist:
  55.             playlist.addItems(media)
  56.         else:
  57.             self.server.createPlaylist(name, media)
  58.  
  59. class Plex2IMDb(threading.Thread):
  60.     imdbpy = IMDb()
  61.     tvdb = api.TVDB('B43FF87DE395DF56')
  62.     thread_limiter = threading.BoundedSemaphore(10)
  63.  
  64.     def __init__(self, plex_obj):
  65.         super().__init__()
  66.         self.plex_obj = plex_obj
  67.         self.imdb_id = None
  68.         self.imdb_keywords = []
  69.  
  70.     def run(self):
  71.         self.thread_limiter.acquire()
  72.         try:
  73.             self.plex_guid = self.get_plex_guid()
  74.             if 'imdb' in self.plex_guid:
  75.                 self.imdb_id = self.get_movie_id()
  76.             elif 'tvdb' in self.plex_guid:
  77.                 self.imdb_id = self.get_episode_id()
  78.             self.imdb_keywords = self.get_imdb_keywords()
  79.         finally:
  80.             self.thread_limiter.release()
  81.  
  82. #    @retry(ConnectTimeout, delay=2)
  83.     def get_plex_guid(self):
  84.         return self.plex_obj.guid
  85.  
  86.     def get_movie_id(self):
  87.         return re.search(r'tt(\d*)\?', self.plex_guid).group()
  88.  
  89.     def get_episode_id(self):
  90.         regex = r'\/\/(\d*)\/(\d*)\/(\d*)'
  91.         series_id, season, episode = map(int, re.search(regex, self.plex_guid).groups())
  92.         series = self.get_tvdb_series(series_id)
  93.  
  94.         try:
  95.             episode = series[season][episode]
  96.         except TVDBIndexError:
  97.             return None
  98.  
  99.         imdb_id = str(episode.IMDB_ID)
  100.         if imdb_id.startswith('tt'):
  101.             return imdb_id[2:]
  102.         return imdb_id
  103.  
  104.     @retry((RemoteDisconnected, ResponseNotReady, AttributeError), delay=2)
  105.     def get_tvdb_series(self, series_id):
  106.         return self.tvdb.get_series(series_id, 'en')
  107.  
  108.     @retry(IMDbDataAccessError, delay=2)
  109.     def get_imdb_keywords(self):
  110.         if not self.imdb_id:
  111.             return []
  112.  
  113.         data = self.imdbpy.get_movie_keywords(self.imdb_id)['data']
  114.         return data.get('keywords', [])
  115.  
  116. def batches(_list, batch_size):
  117.     for i in range(0, len(_list), batch_size):
  118.         yield _list[i:(i+batch_size)]
  119.  
  120. if __name__ == "__main__":
  121.     # Necessary to disable imdbpy logger to hide timeouts, which are handled
  122.     logging.getLogger('imdbpy').disabled = True
  123.     logging.getLogger('imdbpy.parser.http.urlopener').disabled = True
  124.     MAX_THREADS = 100
  125.    
  126.     plex = Plex()
  127.     keyword = input('Keyword (i.e. Holiday name): ').lower()
  128.     playlist_name = input('Playlist name: ')
  129.     threads = []
  130.     keyword_matches = []
  131.  
  132.     print('Scanning', plex.section.title, '...')
  133.     with tqdm(total=len(plex.media)) as pbar:
  134.         for medium in plex.media:
  135.             if keyword in medium.title.lower() or keyword in medium.summary.lower():
  136.                 keyword_matches.append(medium)
  137.                 pbar.update(1)
  138.             else:
  139.                 threads.append(Plex2IMDb(medium))
  140.  
  141.         for batch in batches(threads, MAX_THREADS):
  142.             [ thread.start() for thread in batch ]
  143.             for thread in batch:
  144.                 thread.join()
  145.                 if keyword in thread.imdb_keywords:
  146.                     keyword_matches.append(thread.plex_obj)
  147.                 pbar.update(1)
  148.  
  149.     if keyword_matches:
  150.         print(len(keyword_matches), 'items matching', '\"' + keyword + '\":')
  151.         for match in keyword_matches:
  152.             print('\t', match.title, '(' + str(match.year) + ')')
  153.         plex.create_playlist(playlist_name, keyword_matches)
  154.         print('Playlist created.')
  155.     else:
  156.         print('No matching items, playlist will not be created/updated.')
  157.  
  158.     print('Happy Holidays!')
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement