def check_file_access(m): """Check if we can reach the file directly or if we have to download it via PMS. Args: m (plexapi.video.Episode) Return: filepath or http to the file. """ LOG.debug('Checking if we can reach %s directly', m._prettyfilename()) files = list(m.iterParts()) for file in files: if os.path.exists(file.file): LOG.debug('Found %s', file.file) return file.file else: LOG.warning('Downloading from pms..') try: # for plexapi 3.0.6 and above. return PMS.url('%s?download=1' % file.key, includeToken=True) except TypeError: return PMS.url('%s?download=1' % file.key)
def check_file_access(m): """Check if we can reach the file directly or if we have to download it via PMS. Args: m (plexapi.video.Episode) Return: filepath or http to the file. """ LOG.debug('Checking if we can reach %s directly', m._prettyfilename()) files = list(m.iterParts()) # Now we could get the "wrong" file here. # If the user has duplications we might return the wrong file # CBA with fixing this as it requires to much work :P # And the use case is rather slim, you should never have dupes. # If the user has they can remove them using plex-cli. for file in files: if os.path.exists(file.file): LOG.debug('Found %s', file.file) return file.file else: LOG.warning('Downloading from pms..') try: # for plexapi 3.0.6 and above. return PMS.url('%s?download=1' % file.key, includeToken=True) except TypeError: return PMS.url('%s?download=1' % file.key)
import requests from bs4 import BeautifulSoup from plexapi.myplex import MyPlexAccount from plexapi.server import PlexServer from bw_plex import THEMES, CONFIG, LOG, FP_HASHES # Try to import the optional package. try: import speech_recognition except ImportError: speech_recognition = None LOG.warning( 'Failed to import speech_recognition this is required to check for recaps in audio. ' 'Install the package using pip install bw_plex[audio] or bw_plex[all]') def ignore_ratingkey(item, key): """Helper to check if this is in a ignorelist""" if item.TYPE == 'movie': return item.ratingKey in key if item.TYPE == 'episode': return any( i for i in [item.ratingKey, item.grandparentRatingKey, item.parentRatingKey] if i in key) return False
import os import subprocess import re import sys import click import numpy as np from bw_plex import LOG from bw_plex.misc import sec_to_hh_mm_ss try: import cv2 except ImportError: cv2 = None LOG.warning('Scanning for credits is not supported. ' 'Install the package with pip install bw_plex[all] or bw_plex[video]') try: import pytesseract except ImportError: pytesseract = None LOG.warning('Extracting text from images is not supported. ' 'Install the package with pip install bw_plex[all] or bw_plex[video]') try: import Image except ImportError: from PIL import Image color = {'yellow': (255, 255, 0),
def get_chromecast_player(host=None, name=None): # pragma: no cover """ Get a chromecast preferable using host direcly, if not we will use the name and mnds (slow), if that dont work we will grab the first one. """ try: import pychromecast except ImportError: LOG.warning('Failed to import pychromecast') return None, None # All isnt used atm, lets keep it and # ill fix it later then i create a pr # for plexapi or pychromecast. MESSAGE_TYPE = 'type' TYPE_PLAY = 'PLAY' TYPE_PAUSE = 'PAUSE' TYPE_STOP = 'STOP' TYPE_STEPFORWARD = 'STEPFORWARD' TYPE_STEPBACKWARD = 'STEPBACK' TYPE_PREVIOUS = 'PREVIOUS' TYPE_NEXT = 'NEXT' TYPE_LOAD = 'LOAD' TYPE_DETAILS = 'SHOWDETAILS' TYPE_SEEK = 'SEEK' TYPE_MEDIA_STATUS = 'MEDIA_STATUS' TYPE_GET_STATUS = 'GET_STATUS' TYPE_EDIT_TRACKS_INFO = 'EDIT_TRACKS_INFO' from pychromecast.controllers import BaseController class PlexController(BaseController): """ Controller to interact with Plex namespace. """ def __init__(self): super(PlexController, self).__init__('urn:x-cast:plex', '9AC194DC') self.app_id = '9AC194DC' self.namespace = 'urn:x-cast:plex' self.request_id = 0 self.play_media_event = threading.Event() def _send_cmd(self, msg, namespace=None, inc_session_id=False, callback_function=None, inc=True): """Wrapper the commands.""" self.logger.debug('Sending msg %r %s %s %s %s', msg, namespace, inc_session_id, callback_function, inc) if inc: self._inc_request() if namespace: old = self.namespace try: self.namespace = namespace self.send_message(msg, inc_session_id=inc_session_id, callback_function=callback_function) finally: self.namespace = old else: self.send_message(msg, inc_session_id=inc_session_id, callback_function=callback_function) def _inc_request(self): self.request_id += 1 return self.request_id def receive_message(self, message, data): """ Called when a messag from plex to our controller is received. I havnt seen any message for ut but lets keep for for now, the tests i have done is minimal. """ self.logger.debug('Plex media receive function called.') if data[MESSAGE_TYPE] == TYPE_MEDIA_STATUS: self.logger.debug('(PlexController) MESSAGE RECEIVED: ' + data) return True return False def stop(self): """Send stop command.""" self._send_cmd({MESSAGE_TYPE: TYPE_STOP}) def pause(self): """Send pause command.""" self._send_cmd({MESSAGE_TYPE: TYPE_PAUSE}) def play(self): """Send play command.""" self._send_cmd({MESSAGE_TYPE: TYPE_PLAY}) def previous(self): """Send previous command.""" self._send_cmd({MESSAGE_TYPE: TYPE_PREVIOUS}) def next(self): self._send_cmd({MESSAGE_TYPE: TYPE_NEXT}) def seek(self, position, resume_state='PLAYBACK_START'): """Send seek command""" self._send_cmd({ MESSAGE_TYPE: TYPE_SEEK, 'currentTime': position, 'resumeState': resume_state }) def rewind(self): """Rewind back to the start""" self.seek(0) def set_volume(self, percent): # Feels dirty.. self._socket_client.receiver_controller.set_volume( float(percent / 100)) def volume_up(self, delta=0.1): """ Increment volume by 0.1 (or delta) unless it is already maxed. Returns the new volume. """ if delta <= 0: raise ValueError( "volume delta must be greater than zero, not {}".format( delta)) return self.set_volume(self.status.volume_level + delta) def volume_down(self, delta=0.1): """ Decrement the volume by 0.1 (or delta) unless it is already 0. Returns the new volume. """ if delta <= 0: raise ValueError( "volume delta must be greater than zero, not {}".format( delta)) return self.set_volume(self.status.volume_level - delta) def mute(self, status=None): """ mute the sound. status is just a override. """ if status is not None: st = status else: st = not status.volume_muted self._socket_client.receiver_controller.set_volume_muted(st) def show_media(self, media): """Show the media on the screen, but don't start it.""" msg = media_to_chromecast_command(media, type=TYPE_DETAILS, requestid=self._inc_request()) def cb(): self._send_cmd(msg, inc_session_id=True, inc=False) self.launch(cb) def quit_app(self): """Quit the plex app""" self._socket_client.receiver_controller.stop_app() @property def status(self): # So to get this we could add a listener and update the data ourself # or get can just use socket_clients # status should get a own pr so we can grab the subtitle (episode title.) # Lets just patch this for now.. def episode_title(self): return self.media_metadata.get('subtitle') mc = self._socket_client.media_controller.status mc.episode_title = property(episode_title) return self._socket_client.media_controller.status def disable_subtitle(self): # Shit does not work. """Disable subtitle.""" self._send_cmd( { MESSAGE_TYPE: TYPE_EDIT_TRACKS_INFO, "activeTrackIds": [] }, namespace='urn:x-cast:com.google.cast.media') def _send_start_play(self, media): msg = media_to_chromecast_command(media, requestid=self._inc_request()) self._send_cmd(msg, namespace='urn:x-cast:com.google.cast.media', inc_session_id=True, inc=False) def block_until_playing(self, item, timeout=None): """Helper just incase this is running as a script.""" self.play_media_event.clear() self.play_media(item) self.play_media_event.wait(timeout) self.play_media_event.clear() def play_media(self, item): """Start playback in the chromecast using the selected media. """ self.play_media_event.clear() def app_launched_callback(): try: self._send_start_play(item) finally: self.play_media_event.set() self.launch(app_launched_callback) def join(self, timeout=None): self._socket_client.join(timeout=timeout) def disconnect(self, timeout=None, blocking=True): self._socket_client.disconnect() if blocking: self.join(timeout=timeout) cast = None try: cast = pychromecast.Chromecast(host=host) except pychromecast.ChromecastConnectionError: chromecasts = pychromecast.get_chromecasts() if len(chromecasts) == 1: cast = chromecasts[0] elif len(chromecasts) > 1: cast = next(cc for cc in chromecasts if cc.device.friendly_name == name) else: LOG.warning("Could'nt find any chromecast on you network") return None, None pc = PlexController() cast.register_handler(pc) return pc, cast