예제 #1
0
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)
예제 #2
0
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
예제 #3
0
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)
예제 #4
0
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)
예제 #5
0
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
예제 #6
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."""
        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
예제 #7
0
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
예제 #8
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
예제 #9
0
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
예제 #10
0
파일: omni.py 프로젝트: speedyflipper/omni
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")
예제 #11
0
    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)
예제 #12
0
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))
예제 #13
0
파일: utils.py 프로젝트: Vitor-Tx/kinobot
def check_current_playing_plex():
    plex = PlexServer(PLEX_URL, PLEX_TOKEN)
    return [playing.title for playing in plex.sessions()]
예제 #14
0
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)
예제 #15
0
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
예제 #17
0
    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)
예제 #18
0
파일: plex.py 프로젝트: samip5/Discord-Bots
 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.")
예제 #19
0
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
예제 #20
0
    }

    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
예제 #22
0
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
예제 #23
0
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")
예제 #24
0
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')
예제 #25
0
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
예제 #26
0
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