def __init__(self):
        Activity.on('websocket.playing', self.on_playing)

        self.engine = SessionEngine()
예제 #2
0
    def __init__(self):
        Activity.on('websocket.playing', self.on_playing)

        self.engine = SessionEngine()
class WebSocket(Base):
    name = 'websocket'

    def __init__(self):
        Activity.on('websocket.playing', self.on_playing)

        self.engine = SessionEngine()

    def on_playing(self, info):
        # Create or retrieve existing session
        session = WSessionManager.get.or_create(info, fetch=True)

        # Validate session
        if session.updated_at is None or (datetime.utcnow() - session.updated_at) > timedelta(minutes=5):
            log.info('Updating session, last update was over 5 minutes ago')
            WSessionManager.update(session, info, fetch=True)
            return

        if session.duration is None or session.view_offset is None:
            # Update session
            WSessionManager.update(session, info, fetch=lambda s, i: (
                s.rating_key != to_integer(i.get('ratingKey')) or
                s.duration is None
            ))
            return

        # Parse `info` to events
        events = self.to_events(session, info)

        if not events:
            return

        # Check for changed media
        media_changed = session.rating_key != to_integer(info.get('ratingKey'))

        # Parse `events`
        actions = self.engine.process(session, events)

        for action, payload in actions:
            # Build request for the event
            request = self.build_request(
                session,
                rating_key=payload.get('rating_key'),
                view_offset=payload.get('view_offset')
            )

            if not request:
                continue

            # Queue request to be sent
            ActionManager.queue('/'.join(['scrobble', action]), request, session)

        # Update session
        WSessionManager.update(session, info, fetch=media_changed)

    @classmethod
    def to_events(cls, session, info):
        # Validate `state`
        state = info.get('state')

        if not state:
            log.warn('Event has an invalid state %r', state)
            return []

        if state in IGNORED_EVENTS:
            log.debug('Ignored "%s" event: %r', state, info)
            return []

        # Check for session `view_offset` jump
        if cls.session_jumped(session, info.get('viewOffset')):
            return []

        # Build event
        return [
            (state, {
                'rating_key': to_integer(info.get('ratingKey')),
                'view_offset': to_integer(info.get('viewOffset'))
            })
        ]

    @classmethod
    def test(cls):
        if Plex['status'].sessions() is None:
            log.info("Error while retrieving sessions, assuming WebSocket method isn't available")
            return False

        detail = Plex.detail()
        if detail is None:
            log.info('Error while retrieving server info for testing')
            return False

        if not detail.multiuser:
            log.info("Server info indicates multi-user support isn't available, WebSocket method not available")
            return False

        return True
예제 #4
0
class WebSocket(Base):
    name = 'websocket'

    def __init__(self):
        Activity.on('websocket.playing', self.on_playing)

        self.engine = SessionEngine()

    def on_playing(self, info):
        if InterfaceMessages.critical:
            return

        # Create or retrieve existing session
        session = WSessionManager.get.or_create(info, fetch=True)

        # Validate session
        if session.updated_at is None or (
                datetime.utcnow() - session.updated_at) > timedelta(minutes=5):
            log.info('Updating session, last update was over 5 minutes ago')
            WSessionManager.update(session, info, fetch=True)
            return

        if session.duration is None or session.view_offset is None:
            # Update session
            WSessionManager.update(
                session,
                info,
                fetch=lambda s, i: (s.rating_key != to_integer(
                    i.get('ratingKey')) or s.duration is None))
            return

        # Parse `info` to events
        events = self.to_events(session, info)

        if not events:
            return

        # Check for changed media
        media_changed = session.rating_key != to_integer(info.get('ratingKey'))

        # Parse `events`
        actions = self.engine.process(session, events)

        for action, payload in actions:
            # Build request for the event
            request = self.build_request(
                session,
                part=payload.get('part', 1),
                rating_key=payload.get('rating_key'),
                view_offset=payload.get('view_offset'))

            if not request:
                log.info('No request returned for action %r (payload: %r)',
                         action, payload)
                continue

            # Queue request to be sent
            ActionManager.queue('/'.join(['scrobble', action]), request,
                                session)

        # Update session
        WSessionManager.update(session, info, fetch=media_changed)

    @classmethod
    def to_events(cls, session, info):
        # Validate `state`
        state = info.get('state')

        if not state:
            log.warn('Event has an invalid state %r', state)
            return []

        if state in IGNORED_EVENTS:
            log.debug('Ignored "%s" event: %r', state, info)
            return []

        # Check for session `view_offset` jump
        if cls.session_jumped(session, info.get('viewOffset')):
            return []

        # Retrieve event parameters
        view_offset = to_integer(info.get('viewOffset'))

        # Calculate current part number
        # TODO handle null values from session?
        part, _ = UpdateSession.get_part(session.duration, view_offset,
                                         session.part_count)

        # Build event
        return [(state, {
            'part': part,
            'rating_key': to_integer(info.get('ratingKey')),
            'view_offset': view_offset
        })]

    @classmethod
    def test(cls):
        if Plex['status'].sessions() is None:
            log.info(
                "Error while retrieving sessions, assuming WebSocket method isn't available"
            )
            return False

        detail = Plex.detail()
        if detail is None:
            log.info('Error while retrieving server info for testing')
            return False

        if not detail.multiuser:
            log.info(
                "Server info indicates multi-user support isn't available, WebSocket method not available"
            )
            return False

        return True