def update_video(self, resource: WebsiteContent, privacy=None): """ Update a video's metadata based on a WebsiteContent object that is assumed to have certain fields. """ metadata = resource.metadata description = get_dict_field(metadata, settings.YT_FIELD_DESCRIPTION) speakers = get_dict_field(metadata, settings.YT_FIELD_SPEAKERS) if speakers: description = f"{description}\n\nSpeakers: {speakers}" youtube_id = get_dict_field(metadata, settings.YT_FIELD_ID) self.client.videos().update( part="snippet", body={ "id": youtube_id, "snippet": { "title": truncate_words(strip_bad_chars(resource.title), YT_MAX_LENGTH_TITLE), "description": truncate_words(strip_bad_chars(description), YT_MAX_LENGTH_DESCRIPTION), "tags": get_dict_field(metadata, settings.YT_FIELD_TAGS), "categoryId": settings.YT_CATEGORY_ID, }, }, ).execute() self.update_captions(resource, youtube_id) if privacy: self.update_privacy(youtube_id, privacy=privacy)
def update_youtube_thumbnail(website_id: str, metadata: Dict, overwrite=False): """ Assign a youtube thumbnail url if appropriate to a website's metadata""" website = Website.objects.get(uuid=website_id) if is_ocw_site(website): youtube_id = get_dict_field(metadata, settings.YT_FIELD_ID) if youtube_id and (not get_dict_field( metadata, settings.YT_FIELD_THUMBNAIL) or overwrite): set_dict_field( metadata, settings.YT_FIELD_THUMBNAIL, YT_THUMBNAIL_IMG.format(video_id=youtube_id), )
def update_youtube_metadata(website: Website, version=VERSION_DRAFT): """ Update YouTube video metadata via the API """ if not is_youtube_enabled() or not is_ocw_site(website): return query_id_field = get_dict_query_field("metadata", settings.YT_FIELD_ID) video_resources = website.websitecontent_set.filter( Q(metadata__resourcetype=RESOURCE_TYPE_VIDEO)).exclude( Q(**{query_id_field: None}) | Q(**{query_id_field: ""})) if video_resources.count() == 0: return youtube = YouTubeApi() for video_resource in video_resources: youtube_id = get_dict_field(video_resource.metadata, settings.YT_FIELD_ID) # do not run this for any old imported videos if VideoFile.objects.filter(video__website=website, destination_id=youtube_id).exists(): try: youtube.update_video( video_resource, privacy=("public" if version == VERSION_LIVE else None), ) except: # pylint:disable=bare-except log.exception( "Unexpected error updating metadata for video resource %d", video_resource.id, )
def get_field_to_change(website_content: WebsiteContent, field: str): if field == "markdown": return website_content.markdown if field.startswith("metadata."): metadata_keypath = remove_prefix(field, "metadata.") if website_content.metadata is None: return None return get_dict_field(website_content.metadata, metadata_keypath) raise ValueError(f"Unexpected field value: {field}")
def update_content_from_s3_data(website, text_id, content_data, update_field): """ Update the update_field of a single content file for an ocw course from hugo2ocw output Args: website (Website): The content's website text_id (str): Tthe content's text_id content_data (dict): Dictionary of content data from s3 bucket update_field (str): the field to update Returns: The WebsiteContent object if it existed, None otherwise. """ is_metadata_field = False if update_field and update_field.startswith("metadata."): is_metadata_field = True update_field = update_field.replace("metadata.", "", 1) content_file = WebsiteContent.objects.filter( website=website, text_id=text_id ).first() if not content_file: return None if is_metadata_field: set_dict_field( content_file.metadata, update_field, get_dict_field(content_data.get("metadata", {}), update_field), ) if update_field == "parent_uid" and content_data["parent"]: content_file.parent_id = content_data["parent"].id elif update_field is not None: setattr( content_file, update_field, content_data.get(update_field, ""), ) content_file.save() return content_file
def test_update_transcripts_for_video( settings, mocker, update_transcript_return_value, is_ocw, initial_status, other_incomplete_video, ): """Test update_transcripts_for_video""" mocker.patch("videos.tasks.is_ocw_site", return_value=is_ocw) mocker.patch("websites.api.is_ocw_site", return_value=is_ocw) transcripts_notification_mock = mocker.patch( "videos.tasks.mail_transcripts_complete_notification" ) videofile = VideoFileFactory.create( destination=DESTINATION_YOUTUBE, destination_id="expected_id" ) video = videofile.video video.pdf_transcript_file = "pdf_transcript" video.webvtt_transcript_file = "webvtt_transcript" video.status = initial_status video.save() resource = WebsiteContentFactory.create(website=video.website, metadata={}) metadata = resource.metadata set_nested_dicts(metadata, settings.FIELD_RESOURCETYPE, RESOURCE_TYPE_VIDEO) set_nested_dicts(metadata, settings.YT_FIELD_ID, "expected_id") set_nested_dicts(metadata, settings.YT_FIELD_CAPTIONS, None) set_nested_dicts(metadata, settings.YT_FIELD_TRANSCRIPT, None) resource.save() if other_incomplete_video: other_resource = WebsiteContentFactory.create( website=video.website, metadata={} ) metadata = other_resource.metadata set_nested_dicts(metadata, settings.FIELD_RESOURCETYPE, RESOURCE_TYPE_VIDEO) set_nested_dicts(metadata, settings.YT_FIELD_CAPTIONS, None) other_resource.save() update_transcript_mock = mocker.patch( "videos.tasks.threeplay_api.update_transcripts_for_video", return_value=update_transcript_return_value, ) update_transcripts_for_video(video.id) update_transcript_mock.assert_called_with(video) resource.refresh_from_db() if update_transcript_return_value and is_ocw: assert ( get_dict_field(resource.metadata, settings.YT_FIELD_CAPTIONS) == "webvtt_transcript" ) assert ( get_dict_field(resource.metadata, settings.YT_FIELD_TRANSCRIPT) == "pdf_transcript" ) if initial_status == VideoStatus.SUBMITTED_FOR_TRANSCRIPTION and ( not other_incomplete_video ): transcripts_notification_mock.assert_called_once() else: transcripts_notification_mock.assert_not_called() else: assert get_dict_field(resource.metadata, settings.YT_FIELD_CAPTIONS) is None assert get_dict_field(resource.metadata, settings.YT_FIELD_TRANSCRIPT) is None