Ejemplo n.º 1
0
def save_transcript_to_storage(command_run, edx_video_id, language_code,
                               transcript_content, file_format, force_update):
    """
    Pushes a given transcript's data to django storage.

    Arguments:
        command_run: A positive integer indicating the current run
        edx_video_id: video ID
        language_code: language code
        transcript_content: content of the transcript
        file_format: format of the transcript file
        force_update: tells whether it needs to perform force update in
        case of an existing transcript for the given video.
    """
    transcript_present = is_transcript_available(video_id=edx_video_id,
                                                 language_code=language_code)
    if transcript_present and force_update:
        create_or_update_video_transcript(edx_video_id, language_code,
                                          dict({'file_format': file_format}),
                                          ContentFile(transcript_content))
    elif not transcript_present:
        create_video_transcript(edx_video_id, language_code, file_format,
                                ContentFile(transcript_content))
    else:
        LOGGER.info(
            "[%s] [run=%s] [do-not-override-existing-transcript] [edx_video_id=%s] [language_code=%s]",
            MIGRATION_LOGS_PREFIX, command_run, edx_video_id, language_code)
Ejemplo n.º 2
0
def save_transcript_to_storage(command_run, edx_video_id, language_code, transcript_content, file_format, force_update):
    """
    Pushes a given transcript's data to django storage.

    Arguments:
        command_run: A positive integer indicating the current run
        edx_video_id: video ID
        language_code: language code
        transcript_content: content of the transcript
        file_format: format of the transcript file
        force_update: tells whether it needs to perform force update in
        case of an existing transcript for the given video.
    """
    transcript_present = is_transcript_available(video_id=edx_video_id, language_code=language_code)
    if transcript_present and force_update:
        create_or_update_video_transcript(
            edx_video_id,
            language_code,
            dict({'file_format': file_format}),
            ContentFile(transcript_content)
        )
    elif not transcript_present:
        create_video_transcript(
            edx_video_id,
            language_code,
            file_format,
            ContentFile(transcript_content)
        )
    else:
        LOGGER.info(
            "[%s] [run=%s] [do-not-override-existing-transcript] [edx_video_id=%s] [language_code=%s]",
            MIGRATION_LOGS_PREFIX, command_run, edx_video_id, language_code
        )
    def test_transcript_delete_handler(self, is_staff, is_course_staff):
        """
        Tests that transcript delete handler works as expected with combinations of staff and course's staff.
        """
        # Setup user's roles
        self.user.is_staff = is_staff
        self.user.save()
        course_staff_role = CourseStaffRole(self.course.id)
        if is_course_staff:
            course_staff_role.add_users(self.user)
        else:
            course_staff_role.remove_users(self.user)

        # Assert the user role
        self.assertEqual(self.user.is_staff, is_staff)
        self.assertEqual(CourseStaffRole(self.course.id).has_user(self.user), is_course_staff)

        video_id, language_code = u'1234', u'en'
        # Create a real transcript in VAL.
        api.create_or_update_video_transcript(
            video_id=video_id,
            language_code=language_code,
            metadata={'file_format': 'srt'}
        )

        # Make request to transcript deletion handler
        response = self.client.delete(self.get_url_for_course_key(
            self.course.id,
            edx_video_id=video_id,
            language_code=language_code
        ))
        self.assertEqual(response.status_code, 200)
        self.assertFalse(api.get_video_transcript_data(video_id=video_id, language_code=language_code))
Ejemplo n.º 4
0
def save_transcript_to_storage(edx_video_id, language_code, transcript_content, file_format, force_update):
    """
    Pushes a given transcript's data to django storage.

    Arguments:
        edx_video_id: video ID
        language_code: language code
        transcript_content: content of the transcript
        file_format: format of the transcript file
        force_update: tells whether it needs to perform force update in
        case of an existing transcript for the given video.
    """
    transcript_present = is_transcript_available(video_id=edx_video_id, language_code=language_code)
    if transcript_present and force_update:
        create_or_update_video_transcript(
            edx_video_id,
            language_code,
            dict({'file_format': file_format}),
            ContentFile(transcript_content)
        )
    elif not transcript_present:
        create_video_transcript(
            edx_video_id,
            language_code,
            file_format,
            ContentFile(transcript_content)
        )
Ejemplo n.º 5
0
    def post(self, request):
        """
        Creates a video transcript instance with the given information.

        Arguments:
            request: A WSGI request.
        """
        attrs = ('video_id', 'name', 'language_code', 'provider',
                 'file_format')
        missing = [attr for attr in attrs if attr not in request.data]
        if missing:
            LOGGER.warn('[VAL] Required transcript params are missing. %s',
                        ' and '.join(missing))
            return Response(
                status=status.HTTP_400_BAD_REQUEST,
                data=dict(message=u'{missing} must be specified.'.format(
                    missing=' and '.join(missing))))

        video_id = request.data['video_id']
        language_code = request.data['language_code']
        transcript_name = request.data['name']
        provider = request.data['provider']
        file_format = request.data['file_format']

        supported_formats = sorted(dict(TranscriptFormat.CHOICES).keys())
        if file_format not in supported_formats:
            message = (
                u'"{format}" transcript file type is not supported. Supported formats are "{supported_formats}"'
            ).format(format=file_format, supported_formats=supported_formats)
            return Response(status=status.HTTP_400_BAD_REQUEST,
                            data={'message': message})

        supported_providers = sorted(
            dict(TranscriptProviderType.CHOICES).keys())
        if provider not in supported_providers:
            message = (
                u'"{provider}" provider is not supported. Supported transcription providers are "{supported_providers}"'
            ).format(provider=provider,
                     supported_providers=supported_providers)
            return Response(status=status.HTTP_400_BAD_REQUEST,
                            data={'message': message})

        transcript = VideoTranscript.get_or_none(video_id, language_code)
        if transcript is None:
            create_or_update_video_transcript(video_id,
                                              language_code,
                                              metadata={
                                                  'provider': provider,
                                                  'file_name': transcript_name,
                                                  'file_format': file_format
                                              })
            response = Response(status=status.HTTP_200_OK)
        else:
            message = (
                u'Can not override existing transcript for video "{video_id}" and language code "{language}".'
            ).format(video_id=video_id, language=language_code)
            response = Response(status=status.HTTP_400_BAD_REQUEST,
                                data={'message': message})

        return response
Ejemplo n.º 6
0
def save_video_transcript(edx_video_id, input_format, transcript_content,
                          language_code):
    """
    Saves a video transcript to the VAL and its content to the configured django storage(DS).

    Arguments:
        edx_video_id: A Video ID to associate the transcript.
        input_format: Input transcript format for content being passed.
        transcript_content: Content of the transcript file
        language_code: transcript language code

    Returns:
        A boolean indicating whether the transcript was saved or not.
    """
    try:
        # Convert the transcript into the 'sjson' and upload it to
        # configured transcript storage. For example, S3.
        sjson_subs = Transcript.convert(content=transcript_content,
                                        input_format=input_format,
                                        output_format=Transcript.SJSON)
        create_or_update_video_transcript(
            video_id=edx_video_id,
            language_code=language_code,
            metadata={
                'provider': TranscriptProvider.CUSTOM,
                'file_format': Transcript.SJSON,
                'language_code': language_code
            },
            file_data=ContentFile(sjson_subs),
        )
        result = True
    except (TranscriptsGenerationException, UnicodeDecodeError):
        result = False

    return result
Ejemplo n.º 7
0
    def test_transcript_delete_handler(self, is_staff, is_course_staff):
        """
        Tests that transcript delete handler works as expected with combinations of staff and course's staff.
        """
        # Setup user's roles
        self.user.is_staff = is_staff
        self.user.save()
        course_staff_role = CourseStaffRole(self.course.id)
        if is_course_staff:
            course_staff_role.add_users(self.user)
        else:
            course_staff_role.remove_users(self.user)

        # Assert the user role
        self.assertEqual(self.user.is_staff, is_staff)
        self.assertEqual(
            CourseStaffRole(self.course.id).has_user(self.user),
            is_course_staff)

        video_id, language_code = u'1234', u'en'
        # Create a real transcript in VAL.
        api.create_or_update_video_transcript(video_id=video_id,
                                              language_code=language_code,
                                              metadata={'file_format': 'srt'})

        # Make request to transcript deletion handler
        response = self.client.delete(
            self.get_url_for_course_key(self.course.id,
                                        edx_video_id=video_id,
                                        language_code=language_code))
        self.assertEqual(response.status_code, 200)
        self.assertFalse(
            api.get_video_transcript_data(video_id=video_id,
                                          language_code=language_code))
Ejemplo n.º 8
0
def transcript_upload_handler(request, course_key_string):
    """
    View to upload a transcript file.

    Arguments:
        request: A WSGI request object
        course_key_string: Course key identifying a course

    Transcript file, edx video id and transcript language are required.
    Transcript file should be in SRT(SubRip) format.

    Returns
        - A 400 if any of the validation fails
        - A 404 if the corresponding feature flag is disabled
        - A 200 if transcript has been uploaded successfully
    """
    # Check whether the feature is available for this course.
    course_key = CourseKey.from_string(course_key_string)
    if not VideoTranscriptEnabledFlag.feature_enabled(course_key):
        return HttpResponseNotFound()

    error = validate_transcript_upload_data(data=request.POST, files=request.FILES)
    if error:
        response = JsonResponse({'error': error}, status=400)
    else:
        edx_video_id = request.POST['edx_video_id']
        language_code = request.POST['language_code']
        new_language_code = request.POST['new_language_code']
        transcript_file = request.FILES['file']
        try:
            # Convert SRT transcript into an SJSON format
            # and upload it to S3.
            sjson_subs = Transcript.convert(
                content=transcript_file.read(),
                input_format=Transcript.SRT,
                output_format=Transcript.SJSON
            )
            create_or_update_video_transcript(
                video_id=edx_video_id,
                language_code=language_code,
                metadata={
                    'provider': TranscriptProvider.CUSTOM,
                    'file_format': Transcript.SJSON,
                    'language_code': new_language_code
                },
                file_data=ContentFile(sjson_subs),
            )
            response = JsonResponse(status=201)
        except (TranscriptsGenerationException, UnicodeDecodeError):
            response = JsonResponse(
                {'error': _(u'There is a problem with this transcript file. Try to upload a different file.')},
                status=400
            )

    return response
Ejemplo n.º 9
0
Archivo: views.py Proyecto: edx/edx-val
    def post(self, request):
        """
        Creates a video transcript instance with the given information.

        Arguments:
            request: A WSGI request.
        """
        attrs = ('video_id', 'name', 'language_code', 'provider', 'file_format')
        missing = [attr for attr in attrs if attr not in request.data]
        if missing:
            LOGGER.warn(
                '[VAL] Required transcript params are missing. %s', ' and '.join(missing)
            )
            return Response(
                status=status.HTTP_400_BAD_REQUEST,
                data=dict(message=u'{missing} must be specified.'.format(missing=' and '.join(missing)))
            )

        video_id = request.data['video_id']
        language_code = request.data['language_code']
        transcript_name = request.data['name']
        provider = request.data['provider']
        file_format = request.data['file_format']

        supported_formats = sorted(dict(TranscriptFormat.CHOICES).keys())
        if file_format not in supported_formats:
            message = (
                u'"{format}" transcript file type is not supported. Supported formats are "{supported_formats}"'
            ).format(format=file_format, supported_formats=supported_formats)
            return Response(status=status.HTTP_400_BAD_REQUEST, data={'message': message})

        supported_providers = sorted(dict(TranscriptProviderType.CHOICES).keys())
        if provider not in supported_providers:
            message = (
                u'"{provider}" provider is not supported. Supported transcription providers are "{supported_providers}"'
            ).format(provider=provider, supported_providers=supported_providers)
            return Response(status=status.HTTP_400_BAD_REQUEST, data={'message': message})

        transcript = VideoTranscript.get_or_none(video_id, language_code)
        if transcript is None:
            create_or_update_video_transcript(video_id, language_code, metadata={
                'provider': provider,
                'file_name': transcript_name,
                'file_format': file_format
            })
            response = Response(status=status.HTTP_200_OK)
        else:
            message = (
                u'Can not override existing transcript for video "{video_id}" and language code "{language}".'
            ).format(video_id=video_id, language=language_code)
            response = Response(status=status.HTTP_400_BAD_REQUEST, data={'message': message})

        return response
def transcript_upload_handler(request):
    """
    View to upload a transcript file.

    Arguments:
        request: A WSGI request object

    Transcript file, edx video id and transcript language are required.
    Transcript file should be in SRT(SubRip) format.

    Returns
        - A 400 if any of the validation fails
        - A 200 if transcript has been uploaded successfully
    """
    error = validate_transcript_upload_data(data=request.POST,
                                            files=request.FILES)
    if error:
        response = JsonResponse({'error': error}, status=400)
    else:
        edx_video_id = request.POST['edx_video_id']
        language_code = request.POST['language_code']
        new_language_code = request.POST['new_language_code']
        transcript_file = request.FILES['file']
        try:
            # Convert SRT transcript into an SJSON format
            # and upload it to S3.
            sjson_subs = Transcript.convert(
                content=transcript_file.read().decode('utf-8'),
                input_format=Transcript.SRT,
                output_format=Transcript.SJSON)
            create_or_update_video_transcript(
                video_id=edx_video_id,
                language_code=language_code,
                metadata={
                    'provider': TranscriptProvider.CUSTOM,
                    'file_format': Transcript.SJSON,
                    'language_code': new_language_code
                },
                file_data=ContentFile(sjson_subs),
            )
            response = JsonResponse(status=201)
        except (TranscriptsGenerationException, UnicodeDecodeError):
            response = JsonResponse(
                {
                    'error':
                    _(u'There is a problem with this transcript file. Try to upload a different file.'
                      )
                },
                status=400)

    return response
Ejemplo n.º 11
0
def transcript_upload_handler(request):
    """
    View to upload a transcript file.

    Arguments:
        request: A WSGI request object

    Transcript file, edx video id and transcript language are required.
    Transcript file should be in SRT(SubRip) format.

    Returns
        - A 400 if any of the validation fails
        - A 200 if transcript has been uploaded successfully
    """
    error = validate_transcript_upload_data(data=request.POST, files=request.FILES)
    if error:
        response = JsonResponse({'error': error}, status=400)
    else:
        edx_video_id = request.POST['edx_video_id']
        language_code = request.POST['language_code']
        new_language_code = request.POST['new_language_code']
        transcript_file = request.FILES['file']
        try:
            # Convert SRT transcript into an SJSON format
            # and upload it to S3.
            sjson_subs = Transcript.convert(
                content=transcript_file.read(),
                input_format=Transcript.SRT,
                output_format=Transcript.SJSON
            )
            create_or_update_video_transcript(
                video_id=edx_video_id,
                language_code=language_code,
                metadata={
                    'provider': TranscriptProvider.CUSTOM,
                    'file_format': Transcript.SJSON,
                    'language_code': new_language_code
                },
                file_data=ContentFile(sjson_subs),
            )
            response = JsonResponse(status=201)
        except (TranscriptsGenerationException, UnicodeDecodeError):
            response = JsonResponse(
                {'error': _(u'There is a problem with this transcript file. Try to upload a different file.')},
                status=400
            )

    return response
Ejemplo n.º 12
0
def save_transcript_to_storage(edx_video_id,
                               language_code,
                               transcript_content,
                               file_format=Transcript.SJSON,
                               force_update=False):
    """
    Pushes a given transcript's data to django storage.
    """
    try:
        result = None
        edx_video_id = clean_video_id(edx_video_id)
        if force_update:
            result = create_or_update_video_transcript(
                edx_video_id, language_code, dict({'file_format':
                                                   file_format}),
                ContentFile(transcript_content))
            LOGGER.info(
                "[Transcript migration] save_transcript_to_storage %s for %s with create_or_update method",
                True if result else False, edx_video_id)
        else:
            result = create_video_transcript(edx_video_id, language_code,
                                             file_format,
                                             ContentFile(transcript_content))
            LOGGER.info(
                "[Transcript migration] save_transcript_to_storage %s for %s with create method",
                result, edx_video_id)
        return result
    except ValCannotCreateError as err:
        LOGGER.exception(
            "[Transcript migration] save_transcript_to_storage_failed: %s",
            err)
        raise
Ejemplo n.º 13
0
def upload_transcript(request):
    """
    Upload a transcript file

    Arguments:
        request: A WSGI request object

        Transcript file in SRT format
    """
    edx_video_id = request.POST['edx_video_id']
    language_code = request.POST['language_code']
    new_language_code = request.POST['new_language_code']
    transcript_file = request.FILES['file']
    try:
        # Convert SRT transcript into an SJSON format
        # and upload it to S3.
        sjson_subs = Transcript.convert(
            content=transcript_file.read().decode('utf-8'),
            input_format=Transcript.SRT,
            output_format=Transcript.SJSON).encode()
        create_or_update_video_transcript(
            video_id=edx_video_id,
            language_code=language_code,
            metadata={
                'provider': TranscriptProvider.CUSTOM,
                'file_format': Transcript.SJSON,
                'language_code': new_language_code
            },
            file_data=ContentFile(sjson_subs),
        )
        response = JsonResponse(status=201)
    except (TranscriptsGenerationException, UnicodeDecodeError):
        LOGGER.error(
            "Unable to update transcript on edX video %s for language %s",
            edx_video_id, new_language_code)
        response = JsonResponse(
            {
                'error':
                _('There is a problem with this transcript file. Try to upload a different file.'
                  )
            },
            status=400)
    finally:
        LOGGER.info("Updated transcript on edX video %s for language %s",
                    edx_video_id, new_language_code)
    return response
def upload_transcripts(request):
    """
    Upload transcripts for current module.

    returns: response dict::

        status: 'Success' and HTTP 200 or 'Error' and HTTP 400.
        subs: Value of uploaded and saved html5 sub field in video item.
    """
    error, validated_data = validate_transcript_upload_data(request)
    if error:
        response = JsonResponse({'status': error}, status=400)
    else:
        video = validated_data['video']
        edx_video_id = validated_data['edx_video_id']
        transcript_file = validated_data['transcript_file']
        # check if we need to create an external VAL video to associate the transcript
        # and save its ID on the video component.
        if not edx_video_id:
            edx_video_id = create_external_video(display_name=u'external video')
            video.edx_video_id = edx_video_id
            video.save_with_metadata(request.user)

        response = JsonResponse({'edx_video_id': edx_video_id, 'status': 'Success'}, status=200)

        try:
            # Convert 'srt' transcript into the 'sjson' and upload it to
            # configured transcript storage. For example, S3.
            sjson_subs = Transcript.convert(
                content=transcript_file.read(),
                input_format=Transcript.SRT,
                output_format=Transcript.SJSON
            )
            transcript_created = create_or_update_video_transcript(
                video_id=edx_video_id,
                language_code=u'en',
                metadata={
                    'provider': TranscriptProvider.CUSTOM,
                    'file_format': Transcript.SJSON,
                    'language_code': u'en'
                },
                file_data=ContentFile(sjson_subs),
            )

            if transcript_created is None:
                response = JsonResponse({'status': 'Invalid Video ID'}, status=400)

        except (TranscriptsGenerationException, UnicodeDecodeError):

            response = JsonResponse({
                'status': _(u'There is a problem with this transcript file. Try to upload a different file.')
            }, status=400)

    return response
Ejemplo n.º 15
0
def upload_transcripts(request):
    """
    Upload transcripts for current module.

    returns: response dict::

        status: 'Success' and HTTP 200 or 'Error' and HTTP 400.
        subs: Value of uploaded and saved html5 sub field in video item.
    """
    error, validated_data = validate_transcript_upload_data(request)
    if error:
        response = JsonResponse({'status': error}, status=400)
    else:
        video = validated_data['video']
        edx_video_id = validated_data['edx_video_id']
        transcript_file = validated_data['transcript_file']
        # check if we need to create an external VAL video to associate the transcript
        # and save its ID on the video component.
        if not edx_video_id:
            edx_video_id = create_external_video(display_name=u'external video')
            video.edx_video_id = edx_video_id
            video.save_with_metadata(request.user)

        response = JsonResponse({'edx_video_id': edx_video_id, 'status': 'Success'}, status=200)

        try:
            # Convert 'srt' transcript into the 'sjson' and upload it to
            # configured transcript storage. For example, S3.
            sjson_subs = Transcript.convert(
                content=transcript_file.read(),
                input_format=Transcript.SRT,
                output_format=Transcript.SJSON
            )
            transcript_created = create_or_update_video_transcript(
                video_id=edx_video_id,
                language_code=u'en',
                metadata={
                    'provider': TranscriptProvider.CUSTOM,
                    'file_format': Transcript.SJSON,
                    'language_code': u'en'
                },
                file_data=ContentFile(sjson_subs),
            )

            if transcript_created is None:
                response = JsonResponse({'status': 'Invalid Video ID'}, status=400)

        except (TranscriptsGenerationException, UnicodeDecodeError):

            response = JsonResponse({
                'status': _(u'There is a problem with this transcript file. Try to upload a different file.')
            }, status=400)

    return response
Ejemplo n.º 16
0
def save_video_transcript(edx_video_id, input_format, transcript_content, language_code):
    """
    Saves a video transcript to the VAL and its content to the configured django storage(DS).

    Arguments:
        edx_video_id: A Video ID to associate the transcript.
        input_format: Input transcript format for content being passed.
        transcript_content: Content of the transcript file
        language_code: transcript language code

    Returns:
        A boolean indicating whether the transcript was saved or not.
    """
    try:
        # Convert the transcript into the 'sjson' and upload it to
        # configured transcript storage. For example, S3.
        sjson_subs = Transcript.convert(
            content=transcript_content,
            input_format=input_format,
            output_format=Transcript.SJSON
        )
        create_or_update_video_transcript(
            video_id=edx_video_id,
            language_code=language_code,
            metadata={
                'provider': TranscriptProvider.CUSTOM,
                'file_format': Transcript.SJSON,
                'language_code': language_code
            },
            file_data=ContentFile(sjson_subs),
        )
        result = True
    except (TranscriptsGenerationException, UnicodeDecodeError):
        result = False

    return result
Ejemplo n.º 17
0
def save_transcript_to_storage(
        edx_video_id,
        language_code,
        transcript_content,
        file_format=Transcript.SJSON,
        force_update=False
):
    """
    Pushes a given transcript's data to django storage.
    """
    try:
        result = None
        edx_video_id = clean_video_id(edx_video_id)
        if force_update:
            result = create_or_update_video_transcript(
                edx_video_id,
                language_code,
                dict({'file_format': file_format}),
                ContentFile(transcript_content)
            )
            LOGGER.info("[Transcript migration] save_transcript_to_storage %s for %s with create_or_update method",
                        True if result else False, edx_video_id)
        else:
            result = create_video_transcript(
                edx_video_id,
                language_code,
                file_format,
                ContentFile(transcript_content)
            )
            LOGGER.info(
                "[Transcript migration] save_transcript_to_storage %s for %s with create method",
                result,
                edx_video_id
            )
        return result
    except ValCannotCreateError as err:
        LOGGER.exception("[Transcript migration] save_transcript_to_storage_failed: %s", err)
        raise
Ejemplo n.º 18
0
    def studio_transcript(self, request, dispatch):
        """
        Entry point for Studio transcript handlers.

        Dispatches:
            /translation/[language_id] - language_id sould be in url.

        `translation` dispatch support following HTTP methods:
            `POST`:
                Upload srt file. Check possibility of generation of proper sjson files.
                For now, it works only for self.transcripts, not for `en`.
                Do not update self.transcripts, as fields are updated on save in Studio.
            `GET:
                Return filename from storage. SRT format is sent back on success. Filename should be in GET dict.

        We raise all exceptions right in Studio:
            NotFoundError:
                Video or asset was deleted from module/contentstore, but request came later.
                Seems impossible to be raised. module_render.py catches NotFoundErrors from here.

            /translation POST:
                TypeError:
                    Unjsonable filename or content.
                TranscriptsGenerationException, TranscriptException:
                    no SRT extension or not parse-able by PySRT
                UnicodeDecodeError: non-UTF8 uploaded file content encoding.
        """
        _ = self.runtime.service(self, "i18n").ugettext

        if dispatch.startswith('translation'):

            if request.method == 'POST':
                error = self.validate_transcript_upload_data(data=request.POST)
                if error:
                    response = Response(json={'error': error}, status=400)
                else:
                    edx_video_id = clean_video_id(request.POST['edx_video_id'])
                    language_code = request.POST['language_code']
                    new_language_code = request.POST['new_language_code']
                    transcript_file = request.POST['file'].file

                    if not edx_video_id:
                        # Back-populate the video ID for an external video.
                        # pylint: disable=attribute-defined-outside-init
                        self.edx_video_id = edx_video_id = create_external_video(display_name=u'external video')

                    try:
                        # Convert SRT transcript into an SJSON format
                        # and upload it to S3.
                        sjson_subs = Transcript.convert(
                            content=transcript_file.read(),
                            input_format=Transcript.SRT,
                            output_format=Transcript.SJSON
                        )
                        create_or_update_video_transcript(
                            video_id=edx_video_id,
                            language_code=language_code,
                            metadata={
                                'file_format': Transcript.SJSON,
                                'language_code': new_language_code
                            },
                            file_data=ContentFile(sjson_subs),
                        )
                        payload = {
                            'edx_video_id': edx_video_id,
                            'language_code': new_language_code
                        }
                        response = Response(json.dumps(payload), status=201)
                    except (TranscriptsGenerationException, UnicodeDecodeError):
                        response = Response(
                            json={
                                'error': _(
                                    u'There is a problem with this transcript file. Try to upload a different file.'
                                )
                            },
                            status=400
                        )
            elif request.method == 'DELETE':
                request_data = request.json

                if 'lang' not in request_data or 'edx_video_id' not in request_data:
                    return Response(status=400)

                language = request_data['lang']
                edx_video_id = clean_video_id(request_data['edx_video_id'])

                if edx_video_id:
                    delete_video_transcript(video_id=edx_video_id, language_code=language)

                if language == u'en':
                    # remove any transcript file from content store for the video ids
                    possible_sub_ids = [
                        self.sub,  # pylint: disable=access-member-before-definition
                        self.youtube_id_1_0
                    ] + get_html5_ids(self.html5_sources)
                    for sub_id in possible_sub_ids:
                        remove_subs_from_store(sub_id, self, language)

                    # update metadata as `en` can also be present in `transcripts` field
                    remove_subs_from_store(self.transcripts.pop(language, None), self, language)

                    # also empty `sub` field
                    self.sub = ''  # pylint: disable=attribute-defined-outside-init
                else:
                    remove_subs_from_store(self.transcripts.pop(language, None), self, language)

                return Response(status=200)

            elif request.method == 'GET':
                language = request.GET.get('language_code')
                if not language:
                    return Response(json={'error': _(u'Language is required.')}, status=400)

                try:
                    transcript_content, transcript_name, mime_type = get_transcript(
                        video=self, lang=language, output_format=Transcript.SRT
                    )
                    response = Response(transcript_content, headerlist=[
                        (
                            'Content-Disposition',
                            'attachment; filename="{}"'.format(
                                transcript_name.encode('utf8') if six.PY2 else transcript_name
                            )
                        ),
                        ('Content-Language', language),
                        ('Content-Type', mime_type)
                    ])
                except (UnicodeDecodeError, TranscriptsGenerationException, NotFoundError):
                    response = Response(status=404)

            else:
                # Any other HTTP method is not allowed.
                response = Response(status=404)

        else:  # unknown dispatch
            log.debug("Dispatch is not allowed")
            response = Response(status=404)

        return response
Ejemplo n.º 19
0
    def studio_transcript(self, request, dispatch):
        """
        Entry point for Studio transcript handlers.

        Dispatches:
            /translation/[language_id] - language_id sould be in url.

        `translation` dispatch support following HTTP methods:
            `POST`:
                Upload srt file. Check possibility of generation of proper sjson files.
                For now, it works only for self.transcripts, not for `en`.
                Do not update self.transcripts, as fields are updated on save in Studio.
            `GET:
                Return filename from storage. SRT format is sent back on success. Filename should be in GET dict.

        We raise all exceptions right in Studio:
            NotFoundError:
                Video or asset was deleted from module/contentstore, but request came later.
                Seems impossible to be raised. module_render.py catches NotFoundErrors from here.

            /translation POST:
                TypeError:
                    Unjsonable filename or content.
                TranscriptsGenerationException, TranscriptException:
                    no SRT extension or not parse-able by PySRT
                UnicodeDecodeError: non-UTF8 uploaded file content encoding.
        """
        _ = self.runtime.service(self, "i18n").ugettext

        if dispatch.startswith('translation'):

            if request.method == 'POST':
                error = self.validate_transcript_upload_data(data=request.POST)
                if error:
                    response = Response(json={'error': error}, status=400)
                else:
                    edx_video_id = clean_video_id(request.POST['edx_video_id'])
                    language_code = request.POST['language_code']
                    new_language_code = request.POST['new_language_code']
                    transcript_file = request.POST['file'].file

                    if not edx_video_id:
                        # Back-populate the video ID for an external video.
                        # pylint: disable=attribute-defined-outside-init
                        self.edx_video_id = edx_video_id = create_external_video(display_name=u'external video')

                    try:
                        # Convert SRT transcript into an SJSON format
                        # and upload it to S3.
                        sjson_subs = Transcript.convert(
                            content=transcript_file.read(),
                            input_format=Transcript.SRT,
                            output_format=Transcript.SJSON
                        )
                        create_or_update_video_transcript(
                            video_id=edx_video_id,
                            language_code=language_code,
                            metadata={
                                'file_format': Transcript.SJSON,
                                'language_code': new_language_code
                            },
                            file_data=ContentFile(sjson_subs),
                        )
                        payload = {
                            'edx_video_id': edx_video_id,
                            'language_code': new_language_code
                        }
                        response = Response(json.dumps(payload), status=201)
                    except (TranscriptsGenerationException, UnicodeDecodeError):
                        response = Response(
                            json={
                                'error': _(
                                    u'There is a problem with this transcript file. Try to upload a different file.'
                                )
                            },
                            status=400
                        )
            elif request.method == 'DELETE':
                request_data = request.json

                if 'lang' not in request_data or 'edx_video_id' not in request_data:
                    return Response(status=400)

                language = request_data['lang']
                edx_video_id = clean_video_id(request_data['edx_video_id'])

                if edx_video_id:
                    delete_video_transcript(video_id=edx_video_id, language_code=language)

                if language == u'en':
                    # remove any transcript file from content store for the video ids
                    possible_sub_ids = [
                        self.sub,  # pylint: disable=access-member-before-definition
                        self.youtube_id_1_0
                    ] + get_html5_ids(self.html5_sources)
                    for sub_id in possible_sub_ids:
                        remove_subs_from_store(sub_id, self, language)

                    # update metadata as `en` can also be present in `transcripts` field
                    remove_subs_from_store(self.transcripts.pop(language, None), self, language)

                    # also empty `sub` field
                    self.sub = ''  # pylint: disable=attribute-defined-outside-init
                else:
                    remove_subs_from_store(self.transcripts.pop(language, None), self, language)

                return Response(status=200)

            elif request.method == 'GET':
                language = request.GET.get('language_code')
                if not language:
                    return Response(json={'error': _(u'Language is required.')}, status=400)

                try:
                    transcript_content, transcript_name, mime_type = get_transcript(
                        video=self, lang=language, output_format=Transcript.SRT
                    )
                    response = Response(transcript_content, headerlist=[
                        ('Content-Disposition', 'attachment; filename="{}"'.format(transcript_name.encode('utf8'))),
                        ('Content-Language', language),
                        ('Content-Type', mime_type)
                    ])
                except (UnicodeDecodeError, TranscriptsGenerationException, NotFoundError):
                    response = Response(status=404)

            else:
                # Any other HTTP method is not allowed.
                response = Response(status=404)

        else:  # unknown dispatch
            log.debug("Dispatch is not allowed")
            response = Response(status=404)

        return response