Example #1
0
    def run(cls):
        metadata = {}

        # Retrieve names of test functions
        names = [
            name for name in dir(cls)
            if name.startswith('test_')
        ]

        if not names:
            return cls.on_failure('No tests defined')

        # Run tests
        for name in names:
            # Retrieve function by name
            func = getattr(cls, name, None)

            if not func:
                return cls.on_failure('Unable to find function: %r' % name)

            try:
                # Run test function
                result = func()

                if not result:
                    continue

                # Merge function result into `metadata`
                merge(metadata, result, recursive=True)
            except Exception, ex:
                return cls.on_exception('Exception raised in %r: %s' % (name, ex))
Example #2
0
    def build_failure(cls, message, **kwargs):
        result = {'success': False, 'message': message}

        # Merge extra attributes
        merge(result, kwargs)

        return result
Example #3
0
    def run(cls, search_paths):
        metadata = {}

        message = None
        success = None

        # Retrieve names of test functions
        names = [name for name in dir(cls) if name.startswith('test_')]

        if not names:
            return cls.build_failure('No tests defined')

        # Run tests
        for name in names:
            # Ensure function exists
            if not hasattr(cls, name):
                return cls.build_failure('Unable to find function: %r' % name)

            # Run test
            try:
                result = cls.spawn(name, search_paths)

                # Merge test result into `metadata`
                merge(metadata, result, recursive=True)

                # Test successful
                message = None
                success = True
            except Exception, ex:
                if success:
                    continue

                message = ex.message
                success = False
Example #4
0
    def to_dict(self, obj, info, fetch=False):
        view_offset = to_integer(info.get('time'))
        rating_key = info.get('ratingKey')

        result = {
            'view_offset': view_offset,

            'updated_at': datetime.utcnow()
        }

        if not fetch:
            # Return simple update
            return merge(result, {
                'progress': self.get_progress(obj.duration, view_offset)
            })

        # Retrieve session
        # Retrieve metadata and guid
        p_metadata, guid = self.get_metadata(rating_key)

        if not p_metadata:
            log.warn('Unable to retrieve metadata for rating_key %r', rating_key)
            return result

        if not guid or not guid.valid:
            return merge(result, {
                'duration': p_metadata.duration,
                'progress': self.get_progress(p_metadata.duration, view_offset)
            })

        try:
            # Create/Retrieve `Client` for session
            result['client'] = ClientManager.get.or_create({
                'key': info.get('machineIdentifier'),
                'title': info.get('client')
            }, fetch=True)

            # Create/Retrieve `User` for session
            result['user'] = UserManager.get.or_create({
                'key': to_integer(info.get('user_id')),
                'title': info.get('user_name')
            }, fetch=True)

            # Pick account from `client` or `user` objects
            result['account'] = self.get_account(result)
        except FilteredException:
            log.debug('Activity has been filtered')

            result['client'] = None
            result['user'] = None

            result['account'] = None

        return merge(result, {
            'duration': p_metadata.duration,
            'progress': self.get_progress(p_metadata.duration, view_offset)
        })
Example #5
0
    def on_failure(cls, message, **kwargs):
        result = {
            'success': False,
            'message': message
        }

        # Merge extra attributes
        merge(result, kwargs)

        return result
Example #6
0
    def run(cls, search_paths):
        metadata = {}

        message = None
        success = None

        # Retrieve names of test functions
        names = [
            name for name in dir(cls)
            if name.startswith('test_')
        ]

        if not names:
            return cls.build_failure('No tests defined')

        # Run tests
        for name in names:
            # Ensure function exists
            if not hasattr(cls, name):
                return cls.build_failure('Unable to find function: %r' % name)

            # Run test
            try:
                result = cls.spawn(name, search_paths)

                # Merge test result into `metadata`
                merge(metadata, result, recursive=True)

                # Test successful
                message = None
                success = True
            except Exception as ex:
                if success:
                    continue

                message = ex.message
                success = False

        if not success:
            # Trigger event
            cls.on_failure(message)

            # Build result
            return cls.build_failure(message)

        # Trigger event
        cls.on_success(metadata)

        # Build result
        return cls.build_success(metadata)
Example #7
0
    def fetch(result, player):
        # Fetch client details
        client = Plex.clients().get(player['key'])

        if not client:
            log.info('Unable to find client with key %r', player['key'])
            return result, None

        # Merge client details from plex API
        result = merge(result, dict([
            (key, getattr(client, key)) for key in [
                'device_class',
                'product',
                'version',

                'host',
                'address',
                'port',

                'protocol',
                'protocol_capabilities',
                'protocol_version'
            ] if getattr(client, key)
        ]))

        return result, client
Example #8
0
    def build_request(cls, session, part=None, rating_key=None, view_offset=None):
        # Retrieve metadata for session
        if part is None:
            part = session.part

        if rating_key is None:
            rating_key = session.rating_key

        # Retrieve metadata
        metadata = Metadata.get(rating_key)

        # Validate metadata
        if not metadata:
            log.warn('Unable to retrieve metadata for rating_key %r', rating_key)
            return None

        if metadata.type not in ['movie', 'episode']:
            log.info('Ignoring session with type %r for rating_key %r', metadata.type, rating_key)
            return None

        # Apply library/section filter
        if not Filters.is_valid_metadata_section(metadata):
            log.info('Ignoring session in filtered section: %r', metadata.section.title)
            return None

        # Parse guid
        guid = Guid.parse(metadata.guid, strict=True)

        if not guid or not guid.valid:
            log_unsupported_guid(log, guid)
            return None

        # Build request from guid/metadata
        if type(metadata) is Movie:
            result = cls.build_movie(metadata, guid, part)
        elif type(metadata) is Episode:
            result = cls.build_episode(metadata, guid, part)
        else:
            log.warn('Unknown metadata type: %r', type(metadata))
            return None

        if not result:
            log.info('Unable to build request for session: %r', session)
            return None

        # Retrieve media progress
        if view_offset is not None:
            # Calculate progress from `view_offset` parameter
            progress = UpdateSession.get_progress(
                metadata.duration, view_offset,
                part, session.part_count, session.part_duration
            )
        else:
            # Use session progress
            progress = session.progress

        # Merge progress into request
        return merge(result, {
            'progress': progress
        })
Example #9
0
    def test():
        """Test native libraries to ensure they can be correctly loaded"""
        log.info('Testing native library support...')

        metadata = {}

        for test in LIBRARY_TESTS:
            # Run tests
            result = test.run()

            if not result.get('success'):
                # Write message to logfile
                log.error('%s: unavailable - %s', test.name, result.get('message'), exc_info=result.get('exc_info'))

                if not test.optional:
                    return

                continue

            # Test successful
            t_metadata = result.get('metadata') or {}
            t_versions = t_metadata.get('versions')

            if t_versions:
                if len(t_versions) > 1:
                    log.info('%s: available (%s)', test.name, ', '.join([
                        '%s: %s' % (key, value)
                        for key, value in t_versions.items()
                    ]))
                else:
                    key = t_versions.keys()[0]

                    log.info('%s: available (%s)', test.name, t_versions[key])
            else:
                log.info('%s: available', test.name)

            # Merge result into `metadata`
            merge(metadata, t_metadata, recursive=True)

        # Include versions in error reports
        versions = metadata.get('versions') or {}

        RAVEN.tags.update(dict([
            ('%s.version' % key, value)
            for key, value in versions.items()
        ]))
Example #10
0
    def build_request(cls, session, rating_key=None, view_offset=None):
        # Retrieve metadata for session
        if rating_key is None:
            rating_key = session.rating_key

        # Retrieve metadata
        metadata = Metadata.get(rating_key)

        # Queue a flush for the metadata cache
        Metadata.cache.flush_queue()

        # Validate metadata
        if not metadata:
            log.warn('Unable to retrieve metadata for rating_key %r',
                     rating_key)
            return None

        if metadata.type not in ['movie', 'episode']:
            log.info('Ignoring session with type %r for rating_key %r',
                     metadata.type, rating_key)
            return None

        # Apply library/section filter
        if not Filters.is_valid_metadata_section(metadata):
            return None

        # Parse guid
        guid = Guid.parse(metadata.guid)

        # Build request from guid/metadata
        if type(metadata) is Movie:
            result = cls.build_movie(metadata, guid)
        elif type(metadata) is Episode:
            result = cls.build_episode(metadata, guid)
        else:
            return None

        if not result:
            return None

        # Retrieve media progress
        if view_offset is not None:
            # Calculate progress from `view_offset` parameter
            progress = UpdateSession.get_progress(metadata.duration,
                                                  view_offset)
        else:
            # Use session progress
            progress = session.progress

        # Merge progress into request
        return merge(result, {'progress': progress})
Example #11
0
    def build_request(cls, session, rating_key=None, view_offset=None):
        # Retrieve metadata for session
        if rating_key is None:
            rating_key = session.rating_key

        # Retrieve metadata
        metadata = Metadata.get(rating_key)

        # Queue a flush for the metadata cache
        Metadata.cache.flush_queue()

        # Validate metadata
        if not metadata:
            log.warn('Unable to retrieve metadata for rating_key %r', rating_key)
            return None

        if metadata.type not in ['movie', 'episode']:
            log.info('Ignoring session with type %r for rating_key %r', metadata.type, rating_key)
            return None

        # Apply library/section filter
        if not Filters.is_valid_metadata_section(metadata):
            return None

        # Parse guid
        guid = Guid.parse(metadata.guid)

        # Build request from guid/metadata
        if type(metadata) is Movie:
            result = cls.build_movie(metadata, guid)
        elif type(metadata) is Episode:
            result = cls.build_episode(metadata, guid)
        else:
            return None

        if not result:
            return None

        # Retrieve media progress
        if view_offset is not None:
            # Calculate progress from `view_offset` parameter
            progress = UpdateSession.get_progress(metadata.duration, view_offset)
        else:
            # Use session progress
            progress = session.progress

        # Merge progress into request
        return merge(result, {
            'progress': progress
        })
Example #12
0
        'raven.processors.RemoveStackLocalsProcessor',
        'plugin.raven.processors.RelativePathProcessor'
    ],

    'exclude_paths': [
        'Framework.api',
        'Framework.code',
        'Framework.components',
        'Framework.core',
        'urllib2'
    ],

    # Plugin + System details
    'release': PLUGIN_VERSION,
    'tags': merge(SystemHelper.attributes(), {
        'plugin.version': VERSION,
        'plugin.branch': PLUGIN_VERSION_BRANCH
    })
}

# Configure raven breadcrumbs
breadcrumbs.ignore_logger('plugin.core.logger.handlers.error_reporter.ErrorReporter')
breadcrumbs.ignore_logger('peewee')


class ErrorReporter(Client):
    server = 'sentry.skipthe.net'
    key = 'c0cb82d902b4468cabb01239c22a5642:773fc0ca417b4b1cb29b9b7f75eaadd9'
    project = 1

    def __init__(self, dsn=None, raise_send_errors=False, **options):
        # Build URI
Example #13
0
    def build_request(cls,
                      session,
                      part=None,
                      rating_key=None,
                      view_offset=None):
        # Retrieve metadata for session
        if part is None:
            part = session.part

        if rating_key is None:
            rating_key = session.rating_key

        # Retrieve metadata
        metadata = Metadata.get(rating_key)

        # Validate metadata
        if not metadata:
            log.warn('Unable to retrieve metadata for rating_key %r',
                     rating_key)
            return None

        if metadata.type not in ['movie', 'episode']:
            log.info('Ignoring session with type %r for rating_key %r',
                     metadata.type, rating_key)
            return None

        # Apply library/section filter
        if not Filters.is_valid_metadata_section(metadata):
            log.info('Ignoring session in filtered section: %r',
                     metadata.section.title)
            return None

        # Parse guid
        guid = Guid.parse(metadata.guid, strict=True)

        if not guid or not guid.valid:
            log_unsupported_guid(log, guid)
            return None

        # Build request from guid/metadata
        if type(metadata) is Movie:
            result = cls.build_movie(metadata, guid, part)
        elif type(metadata) is Episode:
            result = cls.build_episode(metadata, guid, part)
        else:
            log.warn('Unknown metadata type: %r', type(metadata))
            return None

        if not result:
            log.info('Unable to build request for session: %r', session)
            return None

        # Retrieve media progress
        if view_offset is not None:
            # Calculate progress from `view_offset` parameter
            progress = UpdateSession.get_progress(metadata.duration,
                                                  view_offset, part,
                                                  session.part_count,
                                                  session.part_duration)
        else:
            # Use session progress
            progress = session.progress

        # Merge progress into request
        return merge(result, {'progress': progress})
Example #14
0
    def test():
        """Test native libraries to ensure they can be correctly loaded"""
        log.info('Testing native library support...')

        # Retrieve library directories
        search_paths = []

        for path in sys.path:
            path_lower = path.lower()

            if 'trakttv.bundle' not in path_lower and 'com.plexapp.plugins.trakttv' not in path_lower:
                continue

            search_paths.append(path)

        # Run library tests
        metadata = {}

        for test in LIBRARY_TESTS:
            # Run tests
            result = test.run(search_paths)

            if not result.get('success'):
                log_func = logging.warn if test.optional else logging.error

                # Write message to logfile
                if 'traceback' in result:
                    log_func('%s: unavailable - %s\n%%s' % (test.name, result.get('message')), result['traceback'])
                else:
                    log_func('%s: unavailable - %s' % (test.name, result.get('message')), exc_info=result.get('exc_info'))

                if not test.optional:
                    return

                continue

            # Test successful
            t_metadata = result.get('metadata') or {}
            t_versions = t_metadata.get('versions')

            if t_versions:
                expanded = len(t_versions) > 1 or (
                    t_versions and t_versions.keys()[0] != test.name
                )

                if expanded:
                    log.info('%s: available (%s)', test.name, ', '.join([
                        '%s: %s' % (key, value)
                        for key, value in t_versions.items()
                    ]))
                else:
                    key = t_versions.keys()[0]

                    log.info('%s: available (%s)', test.name, t_versions[key])
            else:
                log.info('%s: available', test.name)

            # Merge result into `metadata`
            merge(metadata, t_metadata, recursive=True)

        # Include versions in error reports
        versions = metadata.get('versions') or {}
    ],
    'exclude_paths': [
        'Framework.api', 'Framework.code', 'Framework.components',
        'Framework.core', 'urllib2'
    ],

    # Release details
    'release':
    PLUGIN_VERSION,
    'environment':
    ENVIRONMENTS.get(PLUGIN_VERSION_BRANCH, 'development'),

    # Tags
    'tags':
    merge(SystemHelper.attributes(), {
        'plugin.version': VERSION,
        'plugin.branch': PLUGIN_VERSION_BRANCH
    })
}

# Configure raven breadcrumbs
breadcrumbs.ignore_logger(
    'plugin.core.logger.handlers.error_reporter.ErrorReporter')
breadcrumbs.ignore_logger('peewee')


class ErrorReporterClient(Client):
    server = 'sentry.skipthe.net'

    def __init__(self, project, key, raise_send_errors=False, **kwargs):
        self.project = project
        self.key = key
    def to_dict(self, obj, info, fetch=False):
        fetch = resolve(fetch, obj, info)

        view_offset = to_integer(info.get('viewOffset'))

        result = {
            'rating_key': to_integer(info.get('ratingKey')),
            'view_offset': view_offset,
            'updated_at': datetime.utcnow()
        }

        if not fetch:
            # Return simple update
            return merge(
                result,
                {'progress': self.get_progress(obj.duration, view_offset)})

        # Retrieve session key
        session_key = to_integer(info.get('sessionKey'))

        if not session_key:
            log.info('Missing session key, unable to fetch session details')
            return result

        # Retrieve active sessions
        log.debug('Fetching details for session #%s', session_key)

        p_sessions = Plex['status'].sessions()

        if not p_sessions:
            log.info('Unable to retrieve active sessions')
            return result

        # Find session matching `session_key`
        p_item = p_sessions.get(session_key)

        if not p_item:
            log.info('Unable to find session with key %r', session_key)
            return result

        # Retrieve metadata and guid
        p_metadata, guid = self.get_metadata(p_item.rating_key)

        if not p_metadata:
            log.info('Unable to retrieve metadata for rating_key %r',
                     p_item.rating_key)
            return result

        if not guid:
            return merge(
                result, {
                    'duration': p_metadata.duration,
                    'progress': self.get_progress(p_metadata.duration,
                                                  view_offset)
                })

        try:
            # Create/Retrieve `Client` for session
            result['client'] = ClientManager.get.or_create(
                p_item.session.player,
                fetch=True,
                match=True,
                filtered_exception=True)

            # Create/Retrieve `User` for session
            result['user'] = UserManager.get.or_create(p_item.session.user,
                                                       fetch=True,
                                                       match=True,
                                                       filtered_exception=True)

            # Pick account from `client` or `user` objects
            result['account'] = self.get_account(result)
        except FilteredException:
            log.debug('Activity has been filtered')

            result['client'] = None
            result['user'] = None

            result['account'] = None

        return merge(
            result, {
                'duration': p_metadata.duration,
                'progress': self.get_progress(p_metadata.duration, view_offset)
            })
Example #17
0
    def test():
        """Test native libraries to ensure they can be correctly loaded"""
        log.info('Testing native library support...')

        # Retrieve library directories
        search_paths = []

        for path in sys.path:
            path_lower = path.lower()

            if 'trakttv.bundle' not in path_lower and 'com.plexapp.plugins.trakttv' not in path_lower:
                continue

            search_paths.append(path)

        # Run library tests
        metadata = {}

        for test in LIBRARY_TESTS:
            # Run tests
            result = test.run(search_paths)

            if not result.get('success'):
                log_func = logging.warn if test.optional else logging.error

                # Write message to logfile
                if 'traceback' in result:
                    log_func(
                        '%s: unavailable - %s\n%%s' %
                        (test.name, result.get('message')),
                        result['traceback'])
                else:
                    log_func('%s: unavailable - %s' %
                             (test.name, result.get('message')),
                             exc_info=result.get('exc_info'))

                if not test.optional:
                    return

                continue

            # Test successful
            t_metadata = result.get('metadata') or {}
            t_versions = t_metadata.get('versions')

            if t_versions:
                expanded = len(t_versions) > 1 or (
                    t_versions and t_versions.keys()[0] != test.name)

                if expanded:
                    log.info(
                        '%s: available (%s)', test.name, ', '.join([
                            '%s: %s' % (key, value)
                            for key, value in t_versions.items()
                        ]))
                else:
                    key = t_versions.keys()[0]

                    log.info('%s: available (%s)', test.name, t_versions[key])
            else:
                log.info('%s: available', test.name)

            # Merge result into `metadata`
            merge(metadata, t_metadata, recursive=True)

        # Include versions in error reports
        versions = metadata.get('versions') or {}

        RAVEN.tags.update(
            dict([('%s.version' % key, value)
                  for key, value in versions.items()]))
    def to_dict(self, obj, info, fetch=False):
        fetch = resolve(fetch, obj, info)

        view_offset = to_integer(info.get('viewOffset'))

        result = {
            'rating_key': to_integer(info.get('ratingKey')),
            'view_offset': view_offset,

            'updated_at': datetime.utcnow()
        }

        if not fetch:
            # Return simple update
            return merge(result, {
                'progress': self.get_progress(
                    obj.duration, view_offset,
                    obj.part, obj.part_count, obj.part_duration
                )
            })

        # Retrieve session key
        session_key = to_integer(info.get('sessionKey'))

        if not session_key:
            log.info('Missing session key, unable to fetch session details')
            return result

        # Retrieve active sessions
        log.debug('Fetching details for session #%s', session_key)

        p_sessions = Plex['status'].sessions()

        if not p_sessions:
            log.info('Unable to retrieve active sessions')
            return result

        # Find session matching `session_key`
        p_item = p_sessions.get(session_key)

        if not p_item:
            log.info('Unable to find session with key %r', session_key)
            return result

        # Retrieve metadata and guid
        p_metadata, guid = self.get_metadata(p_item.rating_key)

        if not p_metadata:
            log.info('Unable to retrieve metadata for rating_key %r', p_item.rating_key)
            return result

        if not guid or not guid.valid:
            return merge(result, {
                'duration': p_metadata.duration,
                'progress': self.get_progress(p_metadata.duration, view_offset)
            })

        # Retrieve media parts
        part, part_count, part_duration = self.match_parts(p_metadata, guid, view_offset)

        log.debug('Part: %s (part_count: %s, part_duration: %s)', part, part_count, part_duration)

        # Find matching client + user for session
        try:
            # Create/Retrieve `Client` for session
            result['client'] = ClientManager.get.or_create(
                p_item.session.player,

                fetch=True,
                match=True,
                filtered_exception=True
            )

            # Create/Retrieve `User` for session
            result['user'] = UserManager.get.or_create(
                p_item.session.user,

                fetch=True,
                match=True,
                filtered_exception=True
            )

            # Pick account from `client` or `user` objects
            result['account'] = self.get_account(result)
        except FilteredException:
            log.debug('Activity has been filtered')

            result['client'] = None
            result['user'] = None

            result['account'] = None

        return merge(result, {
            'part': part,
            'part_count': part_count,
            'part_duration': part_duration,

            'duration': p_metadata.duration,
            'progress': self.get_progress(
                p_metadata.duration, view_offset,
                part, part_count, part_duration
            )
        })