Пример #1
0
    def handle(self, *args, **options):
        # Create the JWPlatform client
        self.client = jwplatform.get_jwplatform_client()

        # Fetch and cache the video resources
        if not options['skip_video_fetch'] and not options['skip_fetch']:
            self.stdout.write('Caching video resources...')
            models.set_resources(self.fetch_videos(), 'video')

        # Print out the total number of videos cached
        self.stdout.write(self.style.SUCCESS('Number of cached video resources: {}'.format(
            models.CachedResource.videos.count()
        )))

        if not options['skip_channel_fetch'] and not options['skip_fetch']:
            self.stdout.write('Fetching channels...')
            models.set_resources(self.fetch_channels(), 'channel')

        # Print out the total number of channels cached
        self.stdout.write(self.style.SUCCESS('Number of cached channel resources: {}'.format(
            models.CachedResource.channels.count()
        )))

        # Synchronise cached resources into main application state
        sync.update_related_models_from_cache(update_all_videos=options['sync_all'])

        # Print out the total number of media items
        self.stdout.write(self.style.SUCCESS('Number of media items: {}'.format(
            mediaplatform.models.MediaItem.objects.count()
        )))

        # Print out the total number of channels
        self.stdout.write(self.style.SUCCESS('Number of channels: {}'.format(
            mediaplatform.models.Channel.objects.count()
        )))
Пример #2
0
def _perform_item_update(item):
    # Get a JWPlatform client
    jwp_client = jwp.get_jwplatform_client()

    video_resource = {
        'title': item.title,
        # HACK: JWP does not allow a blank description(!)
        'description': item.description if item.description != '' else ' ',

        # We need to populate the SMS fields so that jwpfetch does not overwrite this item
        'custom': {
            'sms_downloadable': 'downloadable:{}:'.format(item.downloadable),
            'sms_language': 'language:{}:'.format(item.language),
            'sms_copyright': 'copyright:{}:'.format(item.copyright),
            'sms_keywords': 'keywords:{}:'.format('|'.join(item.tags)),
        },
    }

    if item.published_at is not None:
        video_resource['date'] = int(item.published_at.timestamp())

    # If there are any permissions, add them too
    if hasattr(item, 'view_permission'):
        video_resource['custom']['sms_acl'] = 'acl:{}:'.format(
            _permission_to_acl(item.view_permission))

    # Convert the model updated_at field to a timestamp
    updated = int(item.updated_at.timestamp())

    if hasattr(item, 'jwp'):
        # Get/create the corresponding cached JWP resource
        video_key = item.jwp.key

        # Update the video using the JWP management API
        response = jwp_client.videos.update(http_method='POST',
                                            video_key=video_key,
                                            **_flatten_dict(video_resource))

        # Record the update
        item.jwp.updated = updated
        item.jwp.save()
    else:
        # Create the video using the JWP management API
        response = jwp_client.videos.create(http_method='POST',
                                            **_flatten_dict(video_resource))

        # Get/create the corresponding cached JWP resource
        video_key = response.get('media', {}).get('key')
        if video_key is None:
            raise RuntimeError('Unexpected response from JWP: {}'.format(
                repr(response)))

        # Create a JWP video model
        models.Video.objects.create(key=video_key, updated=updated, item=item)

    # If there was an upload link in the response, record it.
    link_data = response.get('link')
    if link_data is not None:
        upload.record_link_response(link_data, item)
Пример #3
0
def synchronise(sync_all=False,
                skip_video_fetch=False,
                skip_channel_fetch=False):
    """
    Synchronise the list of Cached JWP resources in the database with the actual list of resources
    using the JWP management API.

    For JWP videos which come from the SMS, media items are automatically created as videos apear.

    All JWP videos with corresponding media items have basic metadata such as title and description
    synchronised.

    If *sync_all* is True, all media items are re-synchronised from their corresponding cached JWP
    resource. If False, only those items whose JWP resources have changed are synchronised.

    If *skip_video_fetch* is True, the cached video resources are not re-fetched from JWP.

    If *skip_channel_fetch* is True, the cached channel resources are not re-fetched from JWP.

    """
    # Create the JWPlatform client
    client = jwplatform.get_jwplatform_client()

    # Fetch and cache the video resources
    if not skip_video_fetch:
        LOG.info('Caching video resources...')
        models.set_resources(fetch_videos(client), 'video')

    # Print out the total number of videos cached
    LOG.info('Number of cached video resources: {}'.format(
        models.CachedResource.videos.count()))

    if not skip_channel_fetch:
        LOG.info('Fetching channels...')
        models.set_resources(fetch_channels(client), 'channel')

    # Print out the total number of channels cached
    LOG.info('Number of cached channel resources: {}'.format(
        models.CachedResource.channels.count()))

    # Synchronise cached resources into main application state
    sync.update_related_models_from_cache(update_all_videos=sync_all)

    # Print out the total number of media items
    LOG.info('Number of media items: {}'.format(
        mediaplatform.models.MediaItem.objects.count()))

    # Print out the total number of channels
    LOG.info('Number of channels: {}'.format(
        mediaplatform.models.Channel.objects.count()))
Пример #4
0
def create_upload_endpoint(item):
    """
    Create an upload endpoint for a media item. Raises ValueError if the item does not have a
    corresponding JWP video

    """
    if not hasattr(item, 'jwp'):
        raise ValueError('MediaItem has no associated JWP video')

    # Get a JWPlatform client
    jwp_client = jwp.get_jwplatform_client()

    response = jwp_client.videos.update(http_method='POST',
                                        video_key=item.jwp.key,
                                        update_file=True)

    upload.record_link_response(response['link'], item)
Пример #5
0
def _perform_item_update(item):
    # Get a JWPlatform client
    jwp_client = jwp.get_jwplatform_client()

    # Form a key for the current site replacing "."s with "_"s since JWP interprets "." specially.
    # NOTE: using get_current() here will use the SITE_ID setting so that must be set.
    current_site = Site.objects.get_current()
    safe_site_name = current_site.domain.replace('.', '_')

    video_resource = {
        'title': item.title,
        # HACK: JWP does not allow a blank description(!)
        'description': item.description if item.description != '' else ' ',
        'custom': {
            # We need to populate the SMS fields so that jwpfetch does not overwrite this item
            'sms_downloadable': 'downloadable:{}:'.format(item.downloadable),
            'sms_language': 'language:{}:'.format(item.language),
            'sms_copyright': 'copyright:{}:'.format(item.copyright),
            'sms_keywords': 'keywords:{}:'.format('|'.join(item.tags)),

            # Add custom props to the video to specify which site it is available on and which
            # media id it corresponds to.
            'site': {
                safe_site_name: {
                    'name': current_site.name,
                    'media_id': item.id,
                },
            }
        },
    }

    # Additional tags which should be set on the video. These tags are added in addition to any
    # existing tags.
    additional_tags = [f'sitedomain:{current_site.domain}']

    # Note: only has an effect if the item is being created
    if item.initially_fetched_from_url != '':
        video_resource['download_url'] = item.initially_fetched_from_url

    if item.published_at is not None:
        video_resource['date'] = int(item.published_at.timestamp())

    # If there are any permissions, add them too
    if hasattr(item, 'view_permission'):
        video_resource['custom']['sms_acl'] = 'acl:{}:'.format(
            _permission_to_acl(item.view_permission))

    # Convert the model updated_at field to a timestamp
    updated = int(item.updated_at.timestamp())

    if hasattr(item, 'jwp'):
        # Get/create the corresponding cached JWP resource
        video_key = item.jwp.key

        # Merge the tags in. JWP seems somewhat cavalier in whitespace surrounding tags and whether
        # the tags field comes back as null or "" so we have to be quite defensive.
        # See: RFC 1122 §1.2.2 and https://en.wikipedia.org/wiki/Robustness_principle
        existing_video = jwp_client.videos.show(video_key=video_key).get(
            'video', {})
        existing_tags = [
            t.strip()
            for t in (existing_video.get('tags') or '').strip().split(',')
        ]
        for t in set(additional_tags) - set(existing_tags):
            existing_tags.append(t)
        video_resource['tags'] = ','.join(existing_tags)

        # Update the video using the JWP management API
        response = jwp_client.videos.update(http_method='POST',
                                            video_key=video_key,
                                            **_flatten_dict(video_resource))

        # Record the update
        item.jwp.updated = updated
        item.jwp.save()
    else:
        # Create the video using the JWP management API
        video_resource['tags'] = ','.join(additional_tags)
        response = jwp_client.videos.create(http_method='POST',
                                            **_flatten_dict(video_resource))

        # Get/create the corresponding cached JWP resource
        resource_data = response.get('media', {})
        video_key = resource_data.get('key')

        # For reasons best known to JWP, the response is different if download_url is set(!)
        if video_key is None:
            video_key = response.get('video', {}).get('key')

            if video_key is not None:
                # We need to fetch the resource again if download_url is set(!)
                resource_data = jwp_client.videos.show(
                    http_method='POST', video_key=video_key)['video']

        if video_key is None:
            raise RuntimeError('Unexpected response from JWP: {}'.format(
                repr(response)))

        # Create a JWP video model and update/create the associated cached resource for it
        resource, _ = models.CachedResource.objects.get_or_create(
            key=video_key, defaults={'data': resource_data})
        models.Video.objects.create(key=video_key,
                                    updated=updated,
                                    item=item,
                                    resource=resource)

    # If there was an upload link in the response, record it.
    link_data = response.get('link')
    if link_data is not None:
        upload.record_link_response(link_data, item)