def get_plexsessions(key): """ Fetch Plex recently added, recently played and now playing. """ values = [] plex = PlexServer() for i, vdata in enumerate(plex.sessions()): video = {} video['user'] = vdata.usernames[0] video['type'] = vdata.type video['year'] = vdata.year video['duration'] = _video_length(vdata.duration) video['viewoffset'] = _video_length(vdata.viewOffset) video['percent'] = round((vdata.viewOffset / vdata.duration) * 100) video['player'] = vdata.players[0].device if vdata.players else 'NA' video['state'] = vdata.players[0].state if vdata.players else 'NA' video[ 'playstate'] = f'{video["viewoffset"]} of {video["duration"]} ({video["percent"]}%)' video['title'] = _video_title(vdata) if video['state'] == 'playing': values.append(video) # Download the thumbnail to cache url = vdata.show( ).thumbUrl if vdata.type == 'episode' else vdata.thumbUrl response = requests.get(url, timeout=REQUEST_TIMEOUT) with open(join(CACHE, f'session{i}.jpg'), 'wb') as handle: handle.write(response.content) if len(values) < 1: _safe_unlink(join(CACHE, 'session0.jpg')) if len(values) < 2: _safe_unlink(join(CACHE, 'session1.jpg')) # save values to cache with open(join(CACHE, f'{key}.json'), 'w') as handle: json.dump(values, handle)
class PlexCollector(BaseCollector): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self._server = PlexServer( self.config['base_url'], self.config['api_token'], ) def get_data_for_sub(self) -> Gdata: tmp = self.get_session_counts() if not tmp: tmp['total'] = 0 return Gdata( plugin='plex', dstypes=['gauge'] * len(tmp), values=list(tmp.values()), dsnames=list(tmp.keys()), dtype_instance='sessions', interval=int(self.config['interval']), ) def get_session_counts(self): sessions = self._server.sessions() # group by type ret = defaultdict(int) for s in sessions: ret[s.type] += 1 ret['total'] += 1 return ret
def hello(): baseurl = 'http://' + SERVER_IP + ':' + PORT plex = PlexServer(baseurl, TOKEN) account = plex.myPlexAccount() art = None showTitle = None title = None username = None sessions = [] for i in plex.sessions(): art = i.artUrl if i.type == 'episode': showTitle = i.grandparentTitle else: showTitle = '' title = i.title username = i.usernames[0] session = { 'art': art, 'showTitle': showTitle, 'title': title, 'username': username } sessions.append(session) return render_template('index.html', sessions=sessions)
def findplayingmedia(): # Connect Remotely but slower #account = MyPlexAccount(credentials.login['username'], credentials.login['password']) #plex = account.resource(credentials.login['plexhost']).connect() # returns a PlexServer instance # Connect faster locally with token credential plex = PlexServer(credentials.login['baseurl'], credentials.login['token']) mediainfos = [] for session in plex.sessions(): mediadict = {} playheadseconds = session.viewOffset // 1000 #Display all instances of the players. #for player in session.players: # print("Player: " + player.device) # this checks if the media being returned is a movie or TV show. if (session.type == "episode"): mediadict["title"] = session.grandparentTitle + " - " + session.title mediadict["type"] = session.type elif (session.type == "movie"): mediadict["title"] = session.title mediadict["type"] = session.type else: print ("not the correct media type playing: " + session.type) mediadict["title"] = "Music" mediadict["type"] = session.type mediadict["convert"] = False if (session.type == "episode") or (session.type == "movie"): # Only for printing out the playehead, checking for accuracy, not otherwise necessary. #minutes, seconds = divmod(int(playheadseconds), 60) #print("Current Playhead Location: " + str(minutes) + ":" + str(seconds)) #searches plex's library for media that matches the key of the session. #this is because I couldn't find a way to consistently get the file path. Sometimes #it would work, sometimes it wouldn't. This made it always work. playingmedia = plex.fetchItem(session.key) playingmediafilepath = playingmedia.media[0].parts[0].file mediadict["playhead"] = playheadseconds mediadict["path"] = playingmediafilepath mediadict["convert"] = True else: mediadict["playhead"] = 0 mediadict["path"] = "No Path" mediadict["id"] = id_generator(8) mediainfos.append(mediadict) return (mediainfos)
class PlexSensor(Entity): """Representation of a Plex now playing sensor.""" # pylint: disable=too-many-arguments def __init__(self, name, plex_url, plex_user, plex_password, plex_server): """Initialize the sensor.""" from plexapi.utils import NA from plexapi.myplex import MyPlexAccount from plexapi.server import PlexServer self._na_type = NA self._name = name self._state = 0 self._now_playing = [] if plex_user and plex_password: user = MyPlexAccount.signin(plex_user, plex_password) server = plex_server if plex_server else user.resources()[0].name self._server = user.resource(server).connect() else: self._server = PlexServer(plex_url) self.update() @property def name(self): """Return the name of the sensor.""" return self._name @property def state(self): """Return the state of the sensor.""" return self._state @property def unit_of_measurement(self): """Return the unit this state is expressed in.""" return "Watching" @property def device_state_attributes(self): """Return the state attributes.""" return {content[0]: content[1] for content in self._now_playing} @Throttle(MIN_TIME_BETWEEN_UPDATES) def update(self): """Update method for Plex sensor.""" sessions = self._server.sessions() now_playing = [] for sess in sessions: user = sess.username if sess.username is not self._na_type else "" title = sess.title if sess.title is not self._na_type else "" year = sess.year if sess.year is not self._na_type else "" now_playing.append((user, "{0} ({1})".format(title, year))) self._state = len(sessions) self._now_playing = now_playing
class PlexSensor(Entity): """Plex now playing sensor.""" # pylint: disable=too-many-arguments def __init__(self, name, plex_url, plex_user, plex_password, plex_server): """Initialize the sensor.""" from plexapi.utils import NA self._na_type = NA self._name = name self._state = 0 self._now_playing = [] if plex_user and plex_password: from plexapi.myplex import MyPlexAccount user = MyPlexAccount.signin(plex_user, plex_password) server = plex_server if plex_server else user.resources()[0].name self._server = user.resource(server).connect() else: from plexapi.server import PlexServer self._server = PlexServer(plex_url) self.update() @property def name(self): """Return the name of the sensor.""" return self._name @property def state(self): """Return the state of the sensor.""" return self._state @property def unit_of_measurement(self): """Return the unit this state is expressed in.""" return "Watching" @property def device_state_attributes(self): """Return the state attributes.""" return {content[0]: content[1] for content in self._now_playing} @Throttle(MIN_TIME_BETWEEN_UPDATES) def update(self): """Update method for plex sensor.""" sessions = self._server.sessions() now_playing = [] for sess in sessions: user = sess.user.title if sess.user is not self._na_type else "" title = sess.title if sess.title is not self._na_type else "" year = sess.year if sess.year is not self._na_type else "" now_playing.append((user, "{0} ({1})".format(title, year))) self._state = len(sessions) self._now_playing = now_playing
class PlexMonitor: def __init__(self, conf): url = conf['url'] token = conf['token'] self.plex = PlexServer(url, token) def current_keepalive_request_s(self): if self.is_active(): return 1 else: return 0 def is_active(self): return len(self.plex.activities) > 0 or len(self.plex.sessions()) > 0
class PlexSensor(Entity): """Plex now playing sensor.""" # pylint: disable=too-many-arguments def __init__(self, name, plex_url, plex_user, plex_password, plex_server): """Initialize the sensor.""" self._name = name self._state = 0 self._now_playing = [] if plex_user and plex_password: from plexapi.myplex import MyPlexUser user = MyPlexUser.signin(plex_user, plex_password) server = plex_server if plex_server else user.resources()[0].name self._server = user.getResource(server).connect() else: from plexapi.server import PlexServer self._server = PlexServer(plex_url) self.update() @property def name(self): """Return the name of the sensor.""" return self._name @property def state(self): """Return the state of the sensor.""" return self._state @property def unit_of_measurement(self): """Return the unit this state is expressed in.""" return "Watching" @property def device_state_attributes(self): """Return the state attributes.""" return {content[0]: content[1] for content in self._now_playing} @Throttle(MIN_TIME_BETWEEN_UPDATES) def update(self): """Update method for plex sensor.""" sessions = self._server.sessions() now_playing = [(s.user.title, "{0} ({1})".format(s.title, s.year)) for s in sessions] self._state = len(sessions) self._now_playing = now_playing
class PlexMonitor: def __init__(self, url, token): self.plex = PlexServer(url, token) def current_keepalive_request_s(self): if self.is_active(): log.info( f'Plex is active with {len(self.plex.sessions())} sessions and {len(self.plex.activities)} activities' ) return 1 else: return 0 def is_active(self): return len(self.plex.activities) > 0 or len(self.plex.sessions()) > 0
def session_search(): plex = PlexServer(conf['plex']['host'], conf['plex']['api']) for x in plex.sessions(): try: logger.info("User: %s is watching %s" % (x.usernames[0], create_plex_title(x))) if x.type == "episode": (series, max_season, season_count) = sonarr_info_by_tvbdb(x.guid.split('/')[2]) if 2 in series['tags']: remaining_episodes = series['totalEpisodeCount'] - ( series['seasons'][0]['statistics']['totalEpisodeCount'] if series['seasons'][0]['seasonNumber'] == 0 else 0) - series['episodeCount'] if remaining_episodes > 0: update_show(series, int(x.parentIndex), season_count, int(x.index)) else: logger.info("Monitoring All Episodes for %s" % series['title']) except: logger.error("Show Not Found in Sonarr")
def run(self): baseurl = '' token = '' player_name = '' previous_album_title = '' while True: plex = PlexServer(baseurl, token) sessions = plex.sessions() for session in sessions: for player in session.players: if player.title == player_name: if previous_album_title != session.parentTitle: previous_album_title = session.parentTitle x = requests.get(session.thumbUrl) if not os.path.isdir('static'): os.mkdir('static') for filename in os.listdir('static/'): if filename.startswith( 'album'): # not to remove other images os.remove('static/' + filename) file_name = f'static/album{str(time.time())}.jpg' album_image = f'album{str(time.time())}.jpg' print(album_image) open(file_name, 'wb').write(x.content) f = open("templates/album.html", "r") test = f.read() f = open("templates/album.html", "w") f.write(test) f.close() sleep(1)
def main(plex_id=None, force=False): logger = logging.getLogger("plex-imdb-updater") db.create_connection("db.sqlite") # Connect to the Plex server logger.info("Connecting to the Plex server at '{base_url}'...".format(base_url=PLEX_URL)) try: plex = PlexServer(PLEX_URL, PLEX_TOKEN) except: logger.error("No Plex server found at: {base_url}".format(base_url=PLEX_URL)) return libraries = [] # Get list of movies from the Plex server for library_name in LIBRARY_NAMES: logger.info("Retrieving a list of movies/shows from the '{library}' library in Plex...".format(library=library_name)) try: libraries.append(plex.library.section(library_name)) except: logger.warning("The '{library}' library does not exist in Plex.".format(library=library_name)) continue if not DRY_RUN: conn_db = sqlite3.connect(PLEX_DATABASE_FILE) conn_db.isolation_level = None database = conn_db.cursor() else: database = None success = 0 failed = 0 for library in libraries: pbar = tqdm(library.all(), postfix=["", ""]) pbar.set_description("Processing " + library.title) for plex_object in pbar: pbar.postfix[0] = plex_object.title pbar.postfix[1] = "Processing" # first do a check if we specified a plex id if plex_id is not None and str(plex_object.ratingKey) != plex_id: continue # check if movie or show library if plex_object.TYPE is "movie": is_movie_library = True if not force and not should_update_media(plex_object.TYPE, plex_object): continue else: is_movie_library = False if not force and not should_update_media(plex_object.TYPE, plex_object): continue # resolve plex object to right identifiers imdb_id, tmdb_id, tvdb_id = resolve_ids(is_movie_library, plex_object, force, pbar) # if no imdb_id is found for plex guid, reset all ratings if not imdb_id: logger.debug("Missing IMDB ID. Skipping media object '{pm.title}'.".format(pm=plex_object)) if not DRY_RUN: db.reset_rating(database, plex_object) db.set_locked_fields(database, plex_object) failed = failed + 1 continue logger.debug("Getting ratings for imdb id '{imdb_id}'".format(imdb_id=imdb_id)) rating = None imdb_object = None # Check if we need to update this if force or should_update_media(plex_object.TYPE, plex_object): # first trying to get it from OMDB if config.OMDB_API_KEY: imdb_object = omdb.get_imdb_rating_from_omdb(imdb_id, pbar) if imdb_object is not None: logger.debug("{im}\t{pm.title}\tOMDB".format(pm=plex_object, im=imdb_object["imdb_rating"])) rating = imdb_object["imdb_rating"] # if no rating yet, try to get it directly from IMDB if (imdb_object is None or rating is None) and imdb.title_exists(imdb_id): imdb_object = imdb.get_title_ratings(imdb_id) if imdb_object is not None and "rating" in imdb_object: logger.debug("{im}\t{pm.title}\tIMDB".format(pm=plex_object, im=imdb_object["rating"])) rating = imdb_object["rating"] # reset in database if nothing could be fetched if rating is None and not DRY_RUN: logger.warning("Media not found on IMDB. Skipping '{pm.title} ({imdb_id})'.".format( pm=plex_object, imdb_id=imdb_id)) if not DRY_RUN: db.reset_rating(database, plex_object) db.set_locked_fields(database, plex_object) failed = failed + 1 continue if is_movie_library: # do update in local library for future reference db_movie = Movie.select().where(Movie.plex_id == plex_object.ratingKey) if db_movie.exists(): db.update_db_rating(db_movie.get(), rating) else: Movie.create( title=plex_object.title, plex_id=plex_object.ratingKey, imdb_id=imdb_id, rating=rating, tmdb_id=tmdb_id, release_date=plex_object.originallyAvailableAt ) else: # do update in local library for future reference db_show = Show.select().where(Show.plex_id == plex_object.ratingKey) if db_show.exists(): db.update_db_rating(db_show.get(), rating) else: Show.create( title=plex_object.title, plex_id=plex_object.ratingKey, imdb_id=imdb_id, rating=rating, release_date=plex_object.originallyAvailableAt, tvdb_id=tvdb_id ) if not DRY_RUN: # if not dry run, do a update in Plex' DB db.set_rating_and_imdb_image(database, plex_object, rating) db.set_locked_fields(database, plex_object) # now try to fetch seasons if not is_movie_library: for season in plex_object.seasons(): # don't do anything with specials if season.index is 0: logger.debug("Skipping specials") continue # check if enabled in settings if EPISODE_RATINGS: logger.debug("Getting episodes for {p.title} for season {season}".format( p=plex_object, season=season.index)) imdb_episodes = None for episode in season.episodes(): update_success = update_episode_rating(database, episode, imdb_episodes, imdb_id, plex_object, season) if update_success: success = success + 1 else: failed = failed + 1 if not DRY_RUN: while len(plex.sessions()) is not 0: logger.info("Plex Media Server in use... waiting 10 seconds before commiting changes") sleep(10) conn_db.commit() if not DRY_RUN: database.close() logger.info("Finished updating. {success} updated and {failed} failed".format(success=success, failed=failed))
def check_current_playing_plex(): plex = PlexServer(PLEX_URL, PLEX_TOKEN) return [playing.title for playing in plex.sessions()]
class PlexClient: def __init__(self, url, host, token): # Init Logger self.__log = logging.getLogger(self.__class__.__name__) # Init Client API session = requests.Session() # TODO handle: session.verify = config.plex_verify_ssl self.__connection = PlexServer(url, token, session=session) self.__host = host # Init Data Attributes self.__active_streams = {} def get_recently_added(self) -> List[PlexMeasurement]: measurements = [] recent_list = [] for section in self.__connection.library.sections(): recent_list += section.recentlyAdded(maxresults=10) for item in recent_list: title = item.title media_type = item.type.title() added_at = item.addedAt.strftime("%Y-%m-%dT%H:%M:%SZ") if hasattr(item, "grandparentTitle"): title = f"{item.grandparentTitle} - {item.title}" # Create Measurement measurement = PlexMeasurement("plex_recently_added", self.__host) measurement.fields = { "title": title, "media_type": media_type, "added_at": added_at, } measurements.append(measurement) return measurements def get_library_data(self) -> List[PlexMeasurement]: measurements = [] libs = self.__connection.library.sections() for library in libs: measurement = PlexMeasurement("plex_libraries", self.__host) measurement.append_tag("type", library.type) measurement.fields = { "title": library.title, "item_count": len(library.search()), } if library.type == "show": seasons = 0 episodes = 0 shows = library.search() for show in shows: seasons += len(show.seasons()) episodes += len(show.episodes()) measurement.fields["season_count"] = seasons measurement.fields["episode_count"] = episodes measurements.append(measurement) return measurements def get_active_streams(self) -> List[PlexMeasurement]: measurements = [] self.__log.debug("Attempting to get active sessions") active_streams = self.__connection.sessions() active_streams = filter(lambda stream: len(stream.session) > 0, active_streams) self.__log.debug("Processing Active Streams") stream_count = 0 for stream in active_streams: stream_count += 1 player = stream.players[0] user = stream.usernames[0] media = stream.media[0] transcode = stream.transcodeSessions[0] if stream.transcodeSessions else None if len(stream.session) == 0: return session_id = stream.session[0].id if session_id in self.__active_streams: start_time = self.__active_streams[session_id]["start_time"] else: start_time = time.time() self.__active_streams[session_id] = {} self.__active_streams[session_id]["start_time"] = start_time # Build the title. TV and Music Have a root title plus episode/track name. Movies don"t if hasattr(stream, "grandparentTitle"): full_title = stream.grandparentTitle + " - " + stream.title else: full_title = stream.title measurement = PlexMeasurement("plex_active_streams", self.__host) measurement.append_tag("player_name", player.title) measurement.append_tag("player_address", player.address) measurement.append_tag("session_id", session_id) measurement.append_tag("title", full_title) measurement.append_tag("user", user) measurement.append_tag("media_type", stream.type) if stream.type != "track": measurement.append_tag("resolution", media.videoResolution) measurement.fields = { "start_time": start_time, "playing": 0 if player.state == "paused" else 1, "bitrate": media.bitrate, "duration": stream.duration, "view_progress": stream.viewOffset/stream.duration*100.0, "transcoding_video": 1 if transcode.videoDecision == "transcode" else 0, "transcoding_audio": 1 if transcode.videoDecision == "transcode" else 0, "transcoding_throttled": transcode.throttled, "transcoding_progress": transcode.progress, } measurements.append(measurement) measurement = PlexMeasurement("active_stream_count", self.__host) measurement.fields["count"] = stream_count measurements.append(measurement) current_streams = map(lambda stream: stream.session[0].id, active_streams) remove_keys = [] for session_id, _ in self.__active_streams.items(): if session_id not in current_streams: remove_keys.append(session_id) for key in remove_keys: self.__active_streams.pop(key) return measurements def _remove_dead_streams(self, current_streams): """ Go through the stored list of active streams and remove any that are no longer active :param current_streams: List of currently active streams from last API call :return: """ remove_keys = [] for key, _ in self.__active_streams.items(): if key not in current_streams: remove_keys.append(key) for key in remove_keys: self.__active_streams.pop(key)
class PlexServerSensor(Entity): """Representation of a Plex now playing sensor.""" def __init__(self, name, plex_url, plex_user, plex_password, plex_server, plex_token): """Initialize the sensor.""" from plexapi.myplex import MyPlexAccount from plexapi.server import PlexServer self._name = name self._state = 0 self._media_attrs = {} self._sessions = None self._session = None self._sessioncount = 0 self._session_type = None self._plex_url = plex_url self._plex_token = plex_token """Set all Media Items to None.""" # General self._media_content_type = None self._media_title = None # TV Show self._media_episode = None self._media_season = None self._media_series_title = None if plex_token: self._server = PlexServer(plex_url, plex_token) elif plex_user and plex_password: user = MyPlexAccount(plex_user, plex_password) server = plex_server if plex_server else user.resources()[0].name self._server = user.resource(server).connect() else: self._server = PlexServer(plex_url) @Throttle(MIN_TIME_BETWEEN_UPDATES) def update(self): """Update method for Plex sensor.""" # new data refresh self._clear_server_details() self._sessions = self._server.sessions() media_attrs = {} for sess in self._sessions: self._session = sess self._sessioncount = self._sessioncount + 1 session_id = 'session_' + str(self._sessioncount) self._session_type = self._session.type # title (movie name, tv episode name, music song name) self._media_title = self._session.title # media type self._set_media_type() if self._session_type == 'episode': media_attrs[session_id] = sess.usernames[ 0] + ' - ' + self._media_series_title + " S" + self._media_season + "E" + self._media_episode + " - " + self._media_title else: media_attrs[ session_id] = sess.usernames[0] + ' - ' + self._media_title if self._sessions is not None: self._state = self._sessioncount self._media_attrs = media_attrs else: self._state = 0 def _clear_server_details(self): self._sessions = None self._sessioncount = 0 self._media_attrs = {} """Set all Media Items to None.""" # General self._media_content_type = None self._media_title = None # TV Show self._media_episode = None self._media_season = None self._media_series_title = None def _set_media_type(self): if self._session_type in ['clip', 'episode']: self._media_content_type = MEDIA_TYPE_TVSHOW # season number (00) if callable(self._session.season): self._media_season = str( (self._session.season()).index).zfill(2) elif self._session.parentIndex is not None: self._media_season = self._session.parentIndex.zfill(2) else: self._media_season = None # show name self._media_series_title = self._session.grandparentTitle # episode number (00) if self._session.index is not None: self._media_episode = str(self._session.index).zfill(2) elif self._session_type == 'movie': self._media_content_type = MEDIA_TYPE_VIDEO if self._session.year is not None and \ self._media_title is not None: self._media_title += ' (' + str(self._session.year) + ')' @property def name(self): """Return the name of the sensor.""" return self._name @property def state(self): """Return the state of the sensor.""" return self._state @property def device_state_attributes(self): """Return the state attributes.""" return self._media_attrs @property def sessions(self): """Return the session, if any.""" return self._sessions @property def sessioncount(self): """Return the session count, if any.""" return self._sessioncount @property def device_state_attributes(self): """Return the state attributes.""" return self._media_attrs
class PlexClientSensor(Entity): """Representation of a Plex now playing sensor.""" def __init__(self, name, plex_url, plex_user, plex_password, plex_server, plex_token, plex_machine_id): """Initialize the sensor.""" from plexapi.myplex import MyPlexAccount from plexapi.server import PlexServer self._name = name self._media_attrs = {} self._plex_machine_id = plex_machine_id self._player_state = 'idle' self._machineIdentifier = plex_machine_id self._device = None self._is_player_active = False self._is_player_available = False self._player = None self._make = 'AppleTV' self._session = None self._session_type = None self._session_username = None self._state = STATE_IDLE self._entity_picture = None self._plex_url = plex_url self._plex_token = plex_token self._media_content_id = None self._media_content_rating = None self._media_content_type = None self._media_duration = None self._media_image_url = None self._media_title = None self._media_ratio = None self._media_episode = None self._media_season = None self._media_series_title = None if plex_token: self._server = PlexServer(plex_url, plex_token) elif plex_user and plex_password: user = MyPlexAccount(plex_user, plex_password) server = plex_server if plex_server else user.resources()[0].name self._server = user.resource(server).connect() else: self._server = PlexServer(plex_url) @Throttle(MIN_TIME_BETWEEN_UPDATES) def update(self): """Update method for Plex sensor.""" # new data refresh self._clear_media_details() devices = self._server.clients() for device in devices: if device.machineIdentifier == self._machineIdentifier: self._device = device sessions = self._server.sessions() for sess in sessions: if sess.players[0].machineIdentifier == self._machineIdentifier: self._session = sess self._is_player_available = True else: self._is_player_available = False if self._session is not None: self._player = self._session.players[0] self._player_state = self._player.state self._session_username = self._session.usernames[0] self._make = self._player.device self._media_ratio = self._session.media[0].aspectRatio self._media_content_id = self._session.ratingKey self._media_content_rating = getattr( self._session, 'contentRating', None) else: self._is_player_available = False self._player_state = None self._entity_picture = '/local/icon/plex.png' self._set_player_state() if self._is_player_active and self._session is not None: self._session_type = self._session.type self._media_duration = self._session.duration # title (movie name, tv episode name, music song name) self._media_title = self._session.title # media type self._set_media_type() self._set_media_image() # calculate duration duration_min = self._media_duration / 60000 hours = int (duration_min / 60) mins = duration_min - hours * 60 length = "%d:%02d" % (hours, mins) media_attrs = {} media_attrs['type'] = self._session_type media_attrs['ratio'] = self._media_ratio media_attrs['rating'] = self._media_content_rating media_attrs['duration'] = length media_attrs['user'] = self._session_username self._entity_picture = self._media_image_url if self._session_type == 'episode': media_attrs['title'] = self._media_series_title + " S" + self._media_season + "E" + self._media_episode + " - " + self._media_title else: media_attrs['title'] = self._media_title self._media_attrs = media_attrs else: self._session_type = None self._media_attrs = {"type": "None", "title": "None", "ratio": "None", "rating": "None", "duration": "None", "user": "******"} def _clear_media_details(self): self._device = None self._session = None """Set all Media Items to None.""" # General self._media_content_id = None self._media_content_rating = None self._media_content_type = None self._media_duration = None self._media_image_url = None self._media_title = None self._media_ratio = None self._entity_picture = None # TV Show self._media_episode = None self._media_season = None self._media_series_title = None def _set_player_state(self): if self._player_state == 'playing': self._is_player_active = True self._state = STATE_PLAYING elif self._player_state == 'paused': self._is_player_active = True self._state = STATE_PAUSED elif self.device: self._is_player_active = False self._state = STATE_IDLE else: self._is_player_active = False self._state = STATE_OFF def _set_media_image(self): thumb_url = self._session.thumbUrl if (self.media_content_type is MEDIA_TYPE_TVSHOW): thumb_url = self._session.url(self._session.grandparentThumb) if thumb_url is None: thumb_url = self._session.url(self._session.art) self._media_image_url = thumb_url def _set_media_type(self): if self._session_type in ['clip', 'episode']: self._media_content_type = MEDIA_TYPE_TVSHOW # season number (00) if callable(self._session.season): self._media_season = str( (self._session.season()).index).zfill(2) elif self._session.parentIndex is not None: self._media_season = self._session.parentIndex.zfill(2) else: self._media_season = None # show name self._media_series_title = self._session.grandparentTitle # episode number (00) if self._session.index is not None: self._media_episode = str(self._session.index).zfill(2) elif self._session_type == 'movie': self._media_content_type = MEDIA_TYPE_VIDEO if self._session.year is not None and \ self._media_title is not None: self._media_title += ' (' + str(self._session.year) + ')' @property def name(self): """Return the name of the sensor.""" return self._name @property def state(self): """Return the state of the sensor.""" return self._state @property def device_state_attributes(self): """Return the state attributes.""" return self._media_attrs @property def entity_picture(self): """Return the entity picture of the sensor.""" return self._entity_picture @property def unique_id(self): """Return the id of this plex client.""" return self._machineIdentifier @property def machine_identifier(self): """Return the machine identifier of the device.""" return self._machineIdentifier @property def device(self): """Return the device, if any.""" return self._device @property def session(self): """Return the session, if any.""" return self._session @property def media_content_id(self): """Return the content ID of current playing media.""" return self._media_content_id @property def media_content_type(self): """Return the content type of current playing media.""" if self._session_type == 'clip': return MEDIA_TYPE_TVSHOW elif self._session_type == 'episode': return MEDIA_TYPE_TVSHOW elif self._session_type == 'movie': return MEDIA_TYPE_VIDEO return None @property def media_duration(self): """Return the duration of current playing media in seconds.""" return self._media_duration @property def media_ratio(self): """Return the aspect ratio of current playing media in seconds.""" return self._media_ratio @property def media_image_url(self): """Return the image URL of current playing media.""" return self._media_image_url @property def media_title(self): """Return the title of current playing media.""" return self._media_title @property def media_season(self): """Return the season of current playing media (TV Show only).""" return self._media_season @property def media_series_title(self): """Return the title of the series of current playing media.""" return self._media_series_title @property def media_episode(self): """Return the episode of current playing media (TV Show only).""" return self._media_episode @property def make(self): """Return the make of the device (ex. SHIELD Android TV).""" return self._make
print('Skip update!') exit(0) print(release.get('url')) name = release.get('url').split('/')[-1] path = '/tmp/{}'.format(name) r = requests.get(release.get('url'), stream=True) if r.status_code != 200: print('Could not download file') with open(path, 'wb') as f: r.raw.decode_content = True shutil.copyfileobj(r.raw, f) while len(plex.sessions()) > 0: print('Waiting for sessions to be over') time.sleep(300) install = ['dpkg', '-i', path] code = call(install, stdout=sys.stdout, stderr=sys.stderr) if code != 0: print('Could not install update!') restart = ['service', 'plexmediaserver', 'restart'] code = call(restart, stdout=sys.stdout, stderr=sys.stderr) if code != 0: print('Could not restart plex!') exit(1) os.remove(path)
async def query_plex_streams(self): sess = requests.Session() sess.verify = False plex = PlexServer(baseurl=PLEX_SRV, token=PLEX_TOKEN, session=sess) session_check = plex.sessions() == [] session_check_not_empty = plex.sessions() != [] for session in plex.sessions(): state = session.players[0].state duration = session.duration duration_millis = session.duration duration_seconds = (duration_millis / 1000) % 60 duration_seconds = int(duration_seconds) duration_minutes = (duration_millis / (1000 * 60)) % 60 duration_minutes = int(duration_minutes) duration_hours = hours = (duration_millis / (1000 * 60 * 60)) % 24 if duration_hours >= 1: total_duration = ("%d Hours and %d Minutes" % (duration_hours, duration_minutes)) else: total_duration = ("%d Minutes" % duration_minutes) view_offset = session.viewOffset view_offset_millis = session.viewOffset view_offset_seconds = (view_offset_millis / 1000) % 60 view_offset_seconds = int(view_offset_seconds) view_offset_minutes = (view_offset_millis / (1000 * 60)) % 60 view_offset_minutes = int(view_offset_minutes) view_offset_hours = hours = (view_offset_millis / (1000 * 60 * 60)) % 24 if view_offset_hours >= 1: offset = ("%d Hours and %d Minutes" % (view_offset_hours, view_offset_minutes)) else: offset = ("%d Minutes" % view_offset_minutes) # print("ms: %d" % (view_offset)) # print("Minutes: %d" % (view_offset_minutes)) # print("Hours: %d" % (view_offset_hours)) percentage = round(view_offset / duration * 100) username = session.usernames[0] if session.type == 'episode': episode_number = int(session.index) season = int(session.parentIndex) season_and_ep_formatted = ("(s%d:e%d)" % (season, episode_number)) current_tv_token = '?checkFiles=1&X-Plex-Token=' + PLEX_TOKEN current_tv_thumb = PLEX_URL + session.thumb + current_tv_token title = session.grandparentTitle + ' - ' + session.title + ' ' + season_and_ep_formatted if session.type == 'movie': year = ("(%d)" % session.year) current_movie_token = '?checkFiles=1&X-Plex-Token=' + PLEX_TOKEN current_movie_thumb = PLEX_URL + session.thumb + current_movie_token # print(current_movie_thumb) title = session.title + ' ' + year state = session.players[0].state player = session.players[0].platform embed = discord.Embed(title="Currently streaming", description="", color=0x00ff00) embed.add_field(name="Username", value="{}".format(username)) embed.add_field(name="Player", value="".join(player), inline=False) embed.add_field(name="Title", value="".join(title), inline=False) embed.add_field(name="State", value="".join(state), inline=False) embed.add_field(name="Watched Duration", value="{watched} ({procent} %)".format( watched=offset, procent=percentage), inline=False) embed.add_field(name="Total Duration", value="".join(total_duration), inline=False) if session.type == 'episode': embed.set_thumbnail(url=current_tv_thumb) else: embed.set_thumbnail(url=current_movie_thumb) embed.set_footer(text="Powered by plexapi.") await self.bot.say(embed=embed) if session_check: await self.bot.say("Nothing is currently streaming.")
class PlexSensor(Entity): """Representation of a Plex now playing sensor.""" def __init__(self, name, plex_url, plex_user, plex_password, plex_server, plex_token, verify_ssl): """Initialize the sensor.""" from plexapi.myplex import MyPlexAccount from plexapi.server import PlexServer from requests import Session self._name = name self._state = 0 self._now_playing = [] cert_session = None if not verify_ssl: _LOGGER.info("Ignoring SSL verification") cert_session = Session() cert_session.verify = False if plex_token: self._server = PlexServer(plex_url, plex_token, cert_session) elif plex_user and plex_password: user = MyPlexAccount(plex_user, plex_password) server = plex_server if plex_server else user.resources()[0].name self._server = user.resource(server).connect() else: self._server = PlexServer(plex_url, None, cert_session) @property def name(self): """Return the name of the sensor.""" return self._name @property def state(self): """Return the state of the sensor.""" return self._state @property def unit_of_measurement(self): """Return the unit this state is expressed in.""" return "Watching" @property def device_state_attributes(self): """Return the state attributes.""" return {content[0]: content[1] for content in self._now_playing} @Throttle(MIN_TIME_BETWEEN_UPDATES) def update(self): """Update method for Plex sensor.""" sessions = self._server.sessions() now_playing = [] for sess in sessions: user = sess.usernames[0] device = sess.players[0].title now_playing_user = "******".format(user, device) now_playing_title = "" if sess.TYPE == 'episode': # example: # "Supernatural (2005) - S01 · E13 - Route 666" season_title = sess.grandparentTitle if sess.show().year is not None: season_title += " ({0})".format(sess.show().year) season_episode = "S{0}".format(sess.parentIndex) if sess.index is not None: season_episode += " · E{0}".format(sess.index) episode_title = sess.title now_playing_title = "{0} - {1} - {2}".format( season_title, season_episode, episode_title) elif sess.TYPE == 'track': # example: # "Billy Talent - Afraid of Heights - Afraid of Heights" track_artist = sess.grandparentTitle track_album = sess.parentTitle track_title = sess.title now_playing_title = "{0} - {1} - {2}".format( track_artist, track_album, track_title) else: # example: # "picture_of_last_summer_camp (2015)" # "The Incredible Hulk (2008)" now_playing_title = sess.title if sess.year is not None: now_playing_title += " ({0})".format(sess.year) now_playing.append((now_playing_user, now_playing_title)) self._state = len(sessions) self._now_playing = now_playing
} try: r = requests.post(TAUTULLI_URL.rstrip('/') + '/api/v2', params=payload) response = r.json() if response['response']['result'] == 'success': sys.stdout.write("Successfully sent Tautulli notification.") else: raise Exception(response['response']['message']) except Exception as e: sys.stderr.write( "Tautulli API 'notify' request failed: {0}.".format(e)) return None if ip_address not in IP_WHITELIST: for session in plex.sessions(): username = session.usernames[0] title = (session.grandparentTitle + ' - ' if session.type == 'episode' else '') + session.title if session.sessionKey == int( sessionKey) and username not in IGNORE_LST: sys.stdout.write( "Killing {user}'s stream of {title}. IP: {ip} not in whitelist" .format(user=username, title=title, ip=ip_address)) session.stop(reason=REASON.format(ip_address)) send_notification( SUBJECT_TEXT, BODY_TEXT.format(user=username, ip=ip_address, title=title))
class PlexAttributes(): def __init__(self, opts): self.opts = opts # command line options self.clsnames = [c for c in opts.clsnames.split(',') if c] # list of clsnames to report (blank=all) self.account = MyPlexAccount() # MyPlexAccount instance self.plex = PlexServer() # PlexServer instance self.total = 0 # Total objects parsed self.attrs = defaultdict(dict) # Attrs result set def run(self): starttime = time.time() self._parse_myplex() self._parse_server() self._parse_search() self._parse_library() self._parse_audio() self._parse_photo() self._parse_movie() self._parse_show() self._parse_client() self._parse_playlist() self._parse_sync() self.runtime = round((time.time() - starttime) / 60.0, 1) return self def _parse_myplex(self): self._load_attrs(self.account, 'myplex') self._load_attrs(self.account.devices(), 'myplex') for resource in self.account.resources(): self._load_attrs(resource, 'myplex') self._load_attrs(resource.connections, 'myplex') self._load_attrs(self.account.users(), 'myplex') def _parse_server(self): self._load_attrs(self.plex, 'serv') self._load_attrs(self.plex.account(), 'serv') self._load_attrs(self.plex.history()[:50], 'hist') self._load_attrs(self.plex.history()[50:], 'hist') self._load_attrs(self.plex.sessions(), 'sess') def _parse_search(self): for search in ('cre', 'ani', 'mik', 'she', 'bea'): self._load_attrs(self.plex.search(search), 'hub') def _parse_library(self): cat = 'lib' self._load_attrs(self.plex.library, cat) # self._load_attrs(self.plex.library.all()[:50], 'all') self._load_attrs(self.plex.library.onDeck()[:50], 'deck') self._load_attrs(self.plex.library.recentlyAdded()[:50], 'add') for search in ('cat', 'dog', 'rat', 'gir', 'mou'): self._load_attrs(self.plex.library.search(search)[:50], 'srch') # TODO: Implement section search (remove library search?) # TODO: Implement section search filters def _parse_audio(self): cat = 'lib' for musicsection in self.plex.library.sections(): if musicsection.TYPE == library.MusicSection.TYPE: self._load_attrs(musicsection, cat) for artist in musicsection.all(): self._load_attrs(artist, cat) for album in artist.albums(): self._load_attrs(album, cat) for track in album.tracks(): self._load_attrs(track, cat) def _parse_photo(self): cat = 'lib' for photosection in self.plex.library.sections(): if photosection.TYPE == library.PhotoSection.TYPE: self._load_attrs(photosection, cat) for photoalbum in photosection.all(): self._load_attrs(photoalbum, cat) for photo in photoalbum.photos(): self._load_attrs(photo, cat) def _parse_movie(self): cat = 'lib' for moviesection in self.plex.library.sections(): if moviesection.TYPE == library.MovieSection.TYPE: self._load_attrs(moviesection, cat) for movie in moviesection.all(): self._load_attrs(movie, cat) def _parse_show(self): cat = 'lib' for showsection in self.plex.library.sections(): if showsection.TYPE == library.ShowSection.TYPE: self._load_attrs(showsection, cat) for show in showsection.all(): self._load_attrs(show, cat) for season in show.seasons(): self._load_attrs(season, cat) for episode in season.episodes(): self._load_attrs(episode, cat) def _parse_client(self): for device in self.account.devices(): client = self._safe_connect(device) if client is not None: self._load_attrs(client, 'myplex') for client in self.plex.clients(): self._safe_connect(client) self._load_attrs(client, 'client') def _parse_playlist(self): for playlist in self.plex.playlists(): self._load_attrs(playlist, 'pl') for item in playlist.items(): self._load_attrs(item, 'pl') playqueue = PlayQueue.create(self.plex, playlist) self._load_attrs(playqueue, 'pq') def _parse_sync(self): # TODO: Get plexattrs._parse_sync() working. pass def _load_attrs(self, obj, cat=None): if isinstance(obj, (list, tuple)): return [self._parse_objects(item, cat) for item in obj] self._parse_objects(obj, cat) def _parse_objects(self, obj, cat=None): clsname = '%s.%s' % (obj.__module__, obj.__class__.__name__) clsname = clsname.replace('plexapi.', '') if self.clsnames and clsname not in self.clsnames: return None self._print_the_little_dot() if clsname not in self.attrs: self.attrs[clsname] = copy.deepcopy(NAMESPACE) self.attrs[clsname]['total'] += 1 self._load_xml_attrs(clsname, obj._data, self.attrs[clsname]['xml'], self.attrs[clsname]['examples'], self.attrs[clsname]['categories'], cat) self._load_obj_attrs(clsname, obj, self.attrs[clsname]['obj'], self.attrs[clsname]['docs']) def _print_the_little_dot(self): self.total += 1 if not self.total % 100: sys.stdout.write('.') if not self.total % 8000: sys.stdout.write('\n') sys.stdout.flush() def _load_xml_attrs(self, clsname, elem, attrs, examples, categories, cat): if elem is None: return None for attr in sorted(elem.attrib.keys()): attrs[attr] += 1 if cat: categories[attr].add(cat) if elem.attrib[attr] and len(examples[attr]) <= self.opts.examples: examples[attr].add(elem.attrib[attr]) for subelem in elem: attrname = TAGATTRS.get(subelem.tag, '%ss' % subelem.tag.lower()) attrs['%s[]' % attrname] += 1 def _load_obj_attrs(self, clsname, obj, attrs, docs): if clsname in STOP_RECURSING_AT: return None if isinstance(obj, PlexObject) and clsname not in DONT_RELOAD: self._safe_reload(obj) alldocs = '\n\n'.join(self._all_docs(obj.__class__)) for attr, value in obj.__dict__.items(): if value is None or isinstance(value, (str, bool, float, int, datetime)): if not attr.startswith('_') and attr not in IGNORES.get( clsname, []): attrs[attr] += 1 if re.search('\s{8}%s\s\(.+?\)\:' % attr, alldocs) is not None: docs[attr] += 1 if isinstance(value, list): if not attr.startswith('_') and attr not in IGNORES.get( clsname, []): if value and isinstance(value[0], PlexObject): attrs['%s[]' % attr] += 1 [self._parse_objects(obj) for obj in value] def _all_docs(self, cls, docs=None): import inspect docs = docs or [] if cls.__doc__ is not None: docs.append(cls.__doc__) for parent in inspect.getmro(cls): if parent != cls: docs += self._all_docs(parent) return docs def print_report(self): total_attrs = 0 for clsname in sorted(self.attrs.keys()): if self._clsname_match(clsname): meta = self.attrs[clsname] count = meta['total'] print(_('\n%s (%s)\n%s' % (clsname, count, '-' * 30), 'yellow')) attrs = sorted( set(list(meta['xml'].keys()) + list(meta['obj'].keys()))) for attr in attrs: state = self._attr_state(clsname, attr, meta) count = meta['xml'].get(attr, 0) categories = ','.join(meta['categories'].get(attr, ['--'])) examples = '; '.join( list(meta['examples'].get(attr, ['--']))[:3])[:80] print('%7s %3s %-30s %-20s %s' % (count, state, attr, categories, examples)) total_attrs += count print(_('\nSUMMARY\n%s' % ('-' * 30), 'yellow')) print('%7s %3s %3s %3s %-20s %s' % ('total', 'new', 'old', 'doc', 'categories', 'clsname')) for clsname in sorted(self.attrs.keys()): if self._clsname_match(clsname): print('%7s %12s %12s %12s %s' % (self.attrs[clsname]['total'], _(self.attrs[clsname]['new'] or '', 'cyan'), _(self.attrs[clsname]['old'] or '', 'red'), _(self.attrs[clsname]['doc'] or '', 'purple'), clsname)) print('\nPlex Version %s' % self.plex.version) print('PlexAPI Version %s' % plexapi.VERSION) print('Total Objects %s' % sum([x['total'] for x in self.attrs.values()])) print('Runtime %s min\n' % self.runtime) def _clsname_match(self, clsname): if not self.clsnames: return True for cname in self.clsnames: if cname.lower() in clsname.lower(): return True return False def _attr_state(self, clsname, attr, meta): if attr in meta['xml'].keys() and attr not in meta['obj'].keys(): self.attrs[clsname]['new'] += 1 return _('new', 'blue') if attr not in meta['xml'].keys() and attr in meta['obj'].keys(): self.attrs[clsname]['old'] += 1 return _('old', 'red') if attr not in meta['docs'].keys() and attr in meta['obj'].keys(): self.attrs[clsname]['doc'] += 1 return _('doc', 'purple') return _(' ', 'green') def _safe_connect(self, elem): try: return elem.connect() except: return None def _safe_reload(self, elem): try: elem.reload() except: pass
class PlexAttributes(): def __init__(self, opts): self.opts = opts # command line options self.clsnames = [c for c in opts.clsnames.split(',') if c] # list of clsnames to report (blank=all) self.account = MyPlexAccount() # MyPlexAccount instance self.plex = PlexServer() # PlexServer instance self.total = 0 # Total objects parsed self.attrs = defaultdict(dict) # Attrs result set def run(self): starttime = time.time() self._parse_myplex() self._parse_server() self._parse_search() self._parse_library() self._parse_audio() self._parse_photo() self._parse_movie() self._parse_show() self._parse_client() self._parse_playlist() self._parse_sync() self.runtime = round((time.time() - starttime) / 60.0, 1) return self def _parse_myplex(self): self._load_attrs(self.account, 'myplex') self._load_attrs(self.account.devices(), 'myplex') for resource in self.account.resources(): self._load_attrs(resource, 'myplex') self._load_attrs(resource.connections, 'myplex') self._load_attrs(self.account.users(), 'myplex') def _parse_server(self): self._load_attrs(self.plex, 'serv') self._load_attrs(self.plex.account(), 'serv') self._load_attrs(self.plex.history()[:50], 'hist') self._load_attrs(self.plex.history()[50:], 'hist') self._load_attrs(self.plex.sessions(), 'sess') def _parse_search(self): for search in ('cre', 'ani', 'mik', 'she', 'bea'): self._load_attrs(self.plex.search(search), 'hub') def _parse_library(self): cat = 'lib' self._load_attrs(self.plex.library, cat) # self._load_attrs(self.plex.library.all()[:50], 'all') self._load_attrs(self.plex.library.onDeck()[:50], 'deck') self._load_attrs(self.plex.library.recentlyAdded()[:50], 'add') for search in ('cat', 'dog', 'rat', 'gir', 'mou'): self._load_attrs(self.plex.library.search(search)[:50], 'srch') # TODO: Implement section search (remove library search?) # TODO: Implement section search filters def _parse_audio(self): cat = 'lib' for musicsection in self.plex.library.sections(): if musicsection.TYPE == library.MusicSection.TYPE: self._load_attrs(musicsection, cat) for artist in musicsection.all(): self._load_attrs(artist, cat) for album in artist.albums(): self._load_attrs(album, cat) for track in album.tracks(): self._load_attrs(track, cat) def _parse_photo(self): cat = 'lib' for photosection in self.plex.library.sections(): if photosection.TYPE == library.PhotoSection.TYPE: self._load_attrs(photosection, cat) for photoalbum in photosection.all(): self._load_attrs(photoalbum, cat) for photo in photoalbum.photos(): self._load_attrs(photo, cat) def _parse_movie(self): cat = 'lib' for moviesection in self.plex.library.sections(): if moviesection.TYPE == library.MovieSection.TYPE: self._load_attrs(moviesection, cat) for movie in moviesection.all(): self._load_attrs(movie, cat) def _parse_show(self): cat = 'lib' for showsection in self.plex.library.sections(): if showsection.TYPE == library.ShowSection.TYPE: self._load_attrs(showsection, cat) for show in showsection.all(): self._load_attrs(show, cat) for season in show.seasons(): self._load_attrs(season, cat) for episode in season.episodes(): self._load_attrs(episode, cat) def _parse_client(self): for device in self.account.devices(): client = self._safe_connect(device) if client is not None: self._load_attrs(client, 'myplex') for client in self.plex.clients(): self._safe_connect(client) self._load_attrs(client, 'client') def _parse_playlist(self): for playlist in self.plex.playlists(): self._load_attrs(playlist, 'pl') for item in playlist.items(): self._load_attrs(item, 'pl') playqueue = PlayQueue.create(self.plex, playlist) self._load_attrs(playqueue, 'pq') def _parse_sync(self): # TODO: Get plexattrs._parse_sync() working. pass def _load_attrs(self, obj, cat=None): if isinstance(obj, (list, tuple)): return [self._parse_objects(item, cat) for item in obj] self._parse_objects(obj, cat) def _parse_objects(self, obj, cat=None): clsname = '%s.%s' % (obj.__module__, obj.__class__.__name__) clsname = clsname.replace('plexapi.', '') if self.clsnames and clsname not in self.clsnames: return None self._print_the_little_dot() if clsname not in self.attrs: self.attrs[clsname] = copy.deepcopy(NAMESPACE) self.attrs[clsname]['total'] += 1 self._load_xml_attrs(clsname, obj._data, self.attrs[clsname]['xml'], self.attrs[clsname]['examples'], self.attrs[clsname]['categories'], cat) self._load_obj_attrs(clsname, obj, self.attrs[clsname]['obj'], self.attrs[clsname]['docs']) def _print_the_little_dot(self): self.total += 1 if not self.total % 100: sys.stdout.write('.') if not self.total % 8000: sys.stdout.write('\n') sys.stdout.flush() def _load_xml_attrs(self, clsname, elem, attrs, examples, categories, cat): if elem is None: return None for attr in sorted(elem.attrib.keys()): attrs[attr] += 1 if cat: categories[attr].add(cat) if elem.attrib[attr] and len(examples[attr]) <= self.opts.examples: examples[attr].add(elem.attrib[attr]) for subelem in elem: attrname = TAGATTRS.get(subelem.tag, '%ss' % subelem.tag.lower()) attrs['%s[]' % attrname] += 1 def _load_obj_attrs(self, clsname, obj, attrs, docs): if clsname in STOP_RECURSING_AT: return None if isinstance(obj, PlexObject) and clsname not in DONT_RELOAD: self._safe_reload(obj) alldocs = '\n\n'.join(self._all_docs(obj.__class__)) for attr, value in obj.__dict__.items(): if value is None or isinstance(value, (str, bool, float, int, datetime)): if not attr.startswith('_') and attr not in IGNORES.get(clsname, []): attrs[attr] += 1 if re.search('\s{8}%s\s\(.+?\)\:' % attr, alldocs) is not None: docs[attr] += 1 if isinstance(value, list): if not attr.startswith('_') and attr not in IGNORES.get(clsname, []): if value and isinstance(value[0], PlexObject): attrs['%s[]' % attr] += 1 [self._parse_objects(obj) for obj in value] def _all_docs(self, cls, docs=None): import inspect docs = docs or [] if cls.__doc__ is not None: docs.append(cls.__doc__) for parent in inspect.getmro(cls): if parent != cls: docs += self._all_docs(parent) return docs def print_report(self): total_attrs = 0 for clsname in sorted(self.attrs.keys()): if self._clsname_match(clsname): meta = self.attrs[clsname] count = meta['total'] print(_('\n%s (%s)\n%s' % (clsname, count, '-' * 30), 'yellow')) attrs = sorted(set(list(meta['xml'].keys()) + list(meta['obj'].keys()))) for attr in attrs: state = self._attr_state(clsname, attr, meta) count = meta['xml'].get(attr, 0) categories = ','.join(meta['categories'].get(attr, ['--'])) examples = '; '.join(list(meta['examples'].get(attr, ['--']))[:3])[:80] print('%7s %3s %-30s %-20s %s' % (count, state, attr, categories, examples)) total_attrs += count print(_('\nSUMMARY\n%s' % ('-' * 30), 'yellow')) print('%7s %3s %3s %3s %-20s %s' % ('total', 'new', 'old', 'doc', 'categories', 'clsname')) for clsname in sorted(self.attrs.keys()): if self._clsname_match(clsname): print('%7s %12s %12s %12s %s' % (self.attrs[clsname]['total'], _(self.attrs[clsname]['new'] or '', 'cyan'), _(self.attrs[clsname]['old'] or '', 'red'), _(self.attrs[clsname]['doc'] or '', 'purple'), clsname)) print('\nPlex Version %s' % self.plex.version) print('PlexAPI Version %s' % plexapi.VERSION) print('Total Objects %s' % sum([x['total'] for x in self.attrs.values()])) print('Runtime %s min\n' % self.runtime) def _clsname_match(self, clsname): if not self.clsnames: return True for cname in self.clsnames: if cname.lower() in clsname.lower(): return True return False def _attr_state(self, clsname, attr, meta): if attr in meta['xml'].keys() and attr not in meta['obj'].keys(): self.attrs[clsname]['new'] += 1 return _('new', 'blue') if attr not in meta['xml'].keys() and attr in meta['obj'].keys(): self.attrs[clsname]['old'] += 1 return _('old', 'red') if attr not in meta['docs'].keys() and attr in meta['obj'].keys(): self.attrs[clsname]['doc'] += 1 return _('doc', 'purple') return _(' ', 'green') def _safe_connect(self, elem): try: return elem.connect() except: return None def _safe_reload(self, elem): try: elem.reload() except: pass
def sessionstatus(): sql = sqlite3.connect(MYDB) cur = sql.cursor() cur.execute('SELECT setting FROM settings WHERE item LIKE \'PLEXUN\'') PLEXUN = cur.fetchone() PLEXUN = str(PLEXUN[0]).strip() cur.execute('SELECT setting FROM settings WHERE item LIKE \'PLEXPW\'') PLEXPW = cur.fetchone() PLEXPW = str(PLEXPW[0]).strip() cur.execute('SELECT setting FROM settings WHERE item LIKE \'PLEXSVR\'') PLEXSVR = cur.fetchone() PLEXSVR = PLEXSVR[0] cur.execute('SELECT setting FROM settings WHERE item LIKE \'PLEXCLIENT\'') PLEXCLIENT = cur.fetchone() PLEXCLIENT = PLEXCLIENT[0] cur.execute( 'SELECT setting FROM settings WHERE item LIKE \'PLEXSERVERIP\'') PLEXSERVERIP = cur.fetchone() PLEXSERVERIP = PLEXSERVERIP[0] cur.execute( 'SELECT setting FROM settings WHERE item LIKE \'PLEXSERVERPORT\'') PLEXSERVERPORT = cur.fetchone() PLEXSERVERPORT = PLEXSERVERPORT[0] from plexapi.myplex import MyPlexAccount try: from plexapi.server import PlexServer baseurl = 'http://' + PLEXSERVERIP + ':' + PLEXSERVERPORT plex = PlexServer(baseurl) print("using local access.") except Exception: print("Local Fail. Trying cloud access.") user = MyPlexAccount.signin(PLEXUN, PLEXPW) plex = user.resource(PLEXSVR).connect() client = plex.client(PLEXCLIENT) psess = plex.sessions() if not psess: return ("Stopped") else: cur.execute( 'SELECT State FROM States WHERE Option LIKE \'Nowplaying\'') nowp = cur.fetchone() nowp = nowp[0] if "TV Show:" in nowp: nowp = nowp.split("Episode: ") nowp = nowp[1] elif "Movie:" in nowp: nowp = nowp.split("Movie: ") nowp = nowp[1] for sess in psess: sess = sess.title if nowp in sess: #print ("Go") return ("Playing") print("Fail") return ("Unknown")
class PlexAttributes(): def __init__(self, opts): self.opts = opts # command line options self.clsnames = [c for c in opts.clsnames.split(',') if c] # list of clsnames to report (blank=all) self.account = MyPlexAccount.signin() # MyPlexAccount instance self.plex = PlexServer() # PlexServer instance self.attrs = defaultdict(dict) # Attrs result set def run(self): # MyPlex self._load_attrs(self.account) self._load_attrs(self.account.devices()) for resource in self.account.resources(): self._load_attrs(resource) self._load_attrs(resource.connections) self._load_attrs(self.account.users()) # Server self._load_attrs(self.plex) self._load_attrs(self.plex.account()) self._load_attrs(self.plex.history()[:20]) self._load_attrs(self.plex.playlists()) for search in ('cre', 'ani', 'mik', 'she'): self._load_attrs(self.plex.search('cre')) self._load_attrs(self.plex.sessions()) # Library self._load_attrs(self.plex.library) self._load_attrs(self.plex.library.sections()) self._load_attrs(self.plex.library.all()[:20]) self._load_attrs(self.plex.library.onDeck()[:20]) self._load_attrs(self.plex.library.recentlyAdded()[:20]) for search in ('cat', 'dog', 'rat'): self._load_attrs(self.plex.library.search(search)[:20]) # Client self._load_attrs(self.plex.clients()) return self def _load_attrs(self, obj): if isinstance(obj, (list, tuple)): return [self._parse_objects(x) for x in obj] return self._parse_objects(obj) def _parse_objects(self, obj): clsname = '%s.%s' % (obj.__module__, obj.__class__.__name__) clsname = clsname.replace('plexapi.', '') if self.clsnames and clsname not in self.clsnames: return None sys.stdout.write('.') sys.stdout.flush() if clsname not in self.attrs: self.attrs[clsname] = copy.deepcopy(NAMESPACE) self.attrs[clsname]['total'] += 1 self._load_xml_attrs(clsname, obj._data, self.attrs[clsname]['xml'], self.attrs[clsname]['examples']) self._load_obj_attrs(clsname, obj, self.attrs[clsname]['obj']) def _load_xml_attrs(self, clsname, elem, attrs, examples): if elem in (None, NA): return None for attr in sorted(elem.attrib.keys()): attrs[attr] += 1 if elem.attrib[attr] and len(examples[attr]) <= self.opts.examples: examples[attr].add(elem.attrib[attr]) def _load_obj_attrs(self, clsname, obj, attrs): for attr, value in obj.__dict__.items(): if value in (None, NA) or isinstance( value, (str, bool, float, int, datetime)): if not attr.startswith('_') and attr not in IGNORES.get( clsname, []): attrs[attr] += 1 def print_report(self): total_attrs = 0 for clsname in sorted(self.attrs.keys()): meta = self.attrs[clsname] count = meta['total'] print( _('\n%s (%s)\n%s' % (clsname, count, '-' * (len(clsname) + 8)), 'yellow')) attrs = sorted( set(list(meta['xml'].keys()) + list(meta['obj'].keys()))) for attr in attrs: state = self._attr_state(attr, meta) count = meta['xml'].get(attr, 0) example = list(meta['examples'].get(attr, ['--']))[0][:80] print('%-4s %4s %-30s %s' % (state, count, attr, example)) total_attrs += count print(_('\nSUMMARY\n------------', 'yellow')) print('Plex Version %s' % self.plex.version) print('PlexAPI Version %s' % plexapi.VERSION) print('Total Objects %s\n' % sum([x['total'] for x in self.attrs.values()])) for clsname in sorted(self.attrs.keys()): print('%-34s %s' % (clsname, self.attrs[clsname]['total'])) print() def _attr_state(self, attr, meta): if attr in meta['xml'].keys() and attr not in meta['obj'].keys(): return _('new', 'blue') if attr not in meta['xml'].keys() and attr in meta['obj'].keys(): return _('old', 'red') return _(' ', 'green')
class PlexSensor(Entity): """Representation of a Plex now playing sensor.""" def __init__(self, name, plex_url, plex_user, plex_password, plex_server): """Initialize the sensor.""" from plexapi.utils import NA from plexapi.myplex import MyPlexAccount from plexapi.server import PlexServer self._na_type = NA self._name = name self._state = 0 self._now_playing = [] if plex_user and plex_password: user = MyPlexAccount.signin(plex_user, plex_password) server = plex_server if plex_server else user.resources()[0].name self._server = user.resource(server).connect() else: self._server = PlexServer(plex_url) self.update() @property def name(self): """Return the name of the sensor.""" return self._name @property def state(self): """Return the state of the sensor.""" return self._state @property def unit_of_measurement(self): """Return the unit this state is expressed in.""" return "Watching" @property def device_state_attributes(self): """Return the state attributes.""" return {content[0]: content[1] for content in self._now_playing} @Throttle(MIN_TIME_BETWEEN_UPDATES) def update(self): """Update method for Plex sensor.""" sessions = self._server.sessions() now_playing = [] for sess in sessions: # user = sess.username if sess.username is not self._na_type else "" # # use player name if username is blank # if user == "": # user = sess.player.title if sess.player.title is not self._na_type else "" # use player name instead of username user = sess.player.title if sess.player.title is not self._na_type else "" title = sess.title if sess.title is not self._na_type else "" # format TV differently from movies if sess.type == 'episode': show = sess.grandparentTitle if sess.grandparentTitle is not self._na_type else "" season = sess.seasonNumber.zfill(2) if sess.seasonNumber is not self._na_type else "" episode = sess.index.zfill(2) if sess.index is not self._na_type else "" now_playing.append((user, "{0} S{1}E{2} - {3}".format(show, season, episode, title))) else: year = sess.year if sess.year is not self._na_type else "" now_playing.append((user, "{0} ({1})".format(title, year))) self._state = len(sessions) self._now_playing = now_playing
class PlexSensor(Entity): """Representation of a Plex now playing sensor.""" def __init__(self, name, plex_url, plex_user, plex_password, plex_server, plex_token): """Initialize the sensor.""" from plexapi.myplex import MyPlexAccount from plexapi.server import PlexServer self._name = name self._state = 0 self._now_playing = [] if plex_token: self._server = PlexServer(plex_url, plex_token) elif plex_user and plex_password: user = MyPlexAccount(plex_user, plex_password) server = plex_server if plex_server else user.resources()[0].name self._server = user.resource(server).connect() else: self._server = PlexServer(plex_url) @property def name(self): """Return the name of the sensor.""" return self._name @property def state(self): """Return the state of the sensor.""" return self._state @property def unit_of_measurement(self): """Return the unit this state is expressed in.""" return "Watching" @property def device_state_attributes(self): """Return the state attributes.""" return {content[0]: content[1] for content in self._now_playing} @Throttle(MIN_TIME_BETWEEN_UPDATES) def update(self): """Update method for Plex sensor.""" sessions = self._server.sessions() now_playing = [] for sess in sessions: user = sess.usernames[0] device = sess.players[0].title now_playing_user = "******".format(user, device) now_playing_title = "" if sess.TYPE == 'episode': # example: # "Supernatural (2005) - S01 · E13 - Route 666" season_title = sess.grandparentTitle if sess.show().year is not None: season_title += " ({0})".format(sess.show().year) season_episode = "S{0}".format(sess.parentIndex) if sess.index is not None: season_episode += " · E{0}".format(sess.index) episode_title = sess.title now_playing_title = "{0} - {1} - {2}".format(season_title, season_episode, episode_title) elif sess.TYPE == 'track': # example: # "Billy Talent - Afraid of Heights - Afraid of Heights" track_artist = sess.grandparentTitle track_album = sess.parentTitle track_title = sess.title now_playing_title = "{0} - {1} - {2}".format(track_artist, track_album, track_title) else: # example: # "picture_of_last_summer_camp (2015)" # "The Incredible Hulk (2008)" now_playing_title = sess.title if sess.year is not None: now_playing_title += " ({0})".format(sess.year) now_playing.append((now_playing_user, now_playing_title)) self._state = len(sessions) self._now_playing = now_playing