Beispiel #1
0
 def get_object(self):
     try:
         video = (Video.objects.select_related('teamvideo').get(
             video_id=self.kwargs['video_id']))
     except Video.DoesNotExist:
         if self.request.user.is_staff:
             raise http.Http404
         else:
             raise PermissionDenied()
     workflow = video.get_workflow()
     if not workflow.user_can_view_video(self.request.user):
         raise PermissionDenied()
     SubtitleLanguage.bulk_has_public_version(
         video.all_subtitle_languages())
     return video
Beispiel #2
0
    def video_management_add_counts(self, videos):
        """Add the subtitle counts for the videos management page

        By default we add the number of completed subtitles, but other
        workflows may want to add other/different counts.

        For each video you can set the counts attribute to a list of strings.
        Each string should describe a count of something, like the number of
        completed subtitles.  The number should be wrapped in a <strong> tag
        (and the whole thing should be wrapped in a mark_safe() call).
        You can also set the counts2 attribute to create a
        second line of counts.

        Args:
            videos -- List of Video instances.
        """
        counts = SubtitleLanguage.count_completed_subtitles(videos)
        for v in videos:
            incomplete_count, completed_count = counts[v.id]
            v.counts = []
            if completed_count > 0:
                msg = ungettext(
                    (u'<strong>%(count)s</strong> subtitle completed'),
                    (u'<strong>%(count)s</strong> subtitles completed'),
                    completed_count)
                v.counts.append(mark_safe(fmt(msg, count=completed_count)))
            if incomplete_count > 0:
                msg = ungettext(
                    (u'<strong>%(count)s</strong> subtitle started'),
                    (u'<strong>%(count)s</strong> subtitles started'),
                    incomplete_count)
                v.counts.append(mark_safe(fmt(msg, count=incomplete_count)))
Beispiel #3
0
    def to_representation(self, qs):
        # Do some optimizations to reduce the number of queries before passing
        # the result to the default to_representation() method

        # Note: we have to use prefetch_related the teamvideo attributes,
        # otherwise it will filter out non-team videos.  I think this is a
        # django 1.4 bug.
        qs = (qs.select_related('teamvideo').prefetch_related(
            'teamvideo__team', 'teamvideo__project', 'newsubtitlelanguage_set',
            'videourl_set'))
        # run bulk_has_public_version(), otherwise we have a query for each
        # language of each video
        videos = list(qs)
        all_languages = []
        for v in videos:
            all_languages.extend(v.all_subtitle_languages())
        SubtitleLanguage.bulk_has_public_version(all_languages)
        return super(VideoListSerializer, self).to_representation(videos)
Beispiel #4
0
    def test_get_language(self):
        sl, needs_save = pipeline._get_language(self.video, 'en')
        self.assertEqual(sl.language_code, 'en')
        self.assertEqual(needs_save, True)

        sl, needs_save = pipeline._get_language(self.video, 'fr')
        self.assertEqual(sl.language_code, 'fr')
        self.assertEqual(needs_save, True)

        l = SubtitleLanguage(video=self.video, language_code='en')
        l.save()

        sl, needs_save = pipeline._get_language(self.video, 'en')
        self.assertEqual(sl.language_code, 'en')
        self.assertEqual(needs_save, False)
        self.assertEqual(sl.id, l.id)

        sl, needs_save = pipeline._get_language(self.video, 'fr')
        self.assertEqual(sl.language_code, 'fr')
        self.assertEqual(needs_save, True)
Beispiel #5
0
def legacy_history(request, video, lang=None):
    """
    In the old days we allowed only one translation per video.
    Therefore video urls looked like /vfjdh2/en/
    Now that this constraint is removed we need to redirect old urls
    to the new view, that needs
    """
    try:
        language = video.subtitle_language(lang)
        if language is None:
            raise SubtitleLanguage.DoesNotExist("No such language")
    except SubtitleLanguage.DoesNotExist:
        raise Http404()

    return HttpResponseRedirect(reverse("videos:translation_history", kwargs={
            'video_id': video.video_id,
            'lang_id': language.pk,
            'lang': language.language_code,
            }))
Beispiel #6
0
def _get_language(video, language_code):
    """Return appropriate SubtitleLanguage and a needs_save boolean.

    If a SubtitleLanguage for this video/language does not exist, an unsaved one
    will be created and returned.  It's up to the caller to save it if
    necessary.

    """
    try:
        # Use select_for_update() to lock the row for the language we're about
        # to update.  Since we know that we're going to do some work, then
        # update the language, locking at the start prevents deadlocks.
        sl = (SubtitleLanguage.objects.select_for_update()
              .get(video=video, language_code=language_code))
        language_needs_save = False
    except SubtitleLanguage.DoesNotExist:
        sl = SubtitleLanguage(video=video, language_code=language_code)
        language_needs_save = True

    return sl, language_needs_save
Beispiel #7
0
class SubtitleEditorBase(View):
    def dispatch(self, request, *args, **kwargs):
        self.handle_special_user(request)
        if not request.user.is_authenticated():
            return redirect_to_login(request.build_absolute_uri())
        return super(SubtitleEditorBase, self).dispatch(
            request, *args, **kwargs)

    def handle_special_user(self, request):
        if 'special_user' not in request.GET:
            return
        try:
            special_user = User.objects.get(id=request.session['editor-user-id'])
        except (KeyError, User.DoesNotExist):
            raise PermissionDenied()
        # We use the editor user for this requests, but still don't log them
        # in.  Note that this will also control the auth headers that get sent
        # to the editor, so the API calls will also use this user.
        request.user = special_user

    def get_video_urls(self):
        """Get video URLs to send to the editor."""
        return self.workflow.editor_video_urls(self.language_code)

    def get_redirect_url(self):
        if 'return_url' in self.request.GET:
            return self.request.GET['return_url']
        else:
            return self.video.get_absolute_url()

    def get_custom_css(self):
        return ""

    def get_title(self):
        return _('Amara')

    def get_analytics_additions(self):
        return None

    def calc_base_language(self):
        if (self.video.primary_audio_language_code and 
            SubtitleVersion.objects.extant().filter(
                video=self.video,
                language_code=self.video.primary_audio_language_code)
            .exists()):
            self.base_language = self.video.primary_audio_language_code
        else:
            self.base_language = None

    def calc_editing_language(self):
        self.editing_language = self.video.subtitle_language(self.language_code)
        if self.editing_language is None:
            self.editing_language = SubtitleLanguage(
                video=self.video, language_code=self.language_code)

    def check_can_writelock(self):
        if not self.editing_language.can_writelock(self.request.browser_id):
            msg = _("You can't edit this subtitle because it's locked")
            messages.error(self.request, msg)
            return False
        else:
            return True

    def check_can_edit(self):
        if self.workflow.user_can_edit_subtitles(self.user,
                                                 self.language_code):
            return True
        messages.error(self.request,
                       _('Sorry, these subtitles are privately moderated.'))
        return False

    def get_editor_data(self):
        editor_data = {
            'canSync': bool(self.request.GET.get('canSync', True)),
            'canAddAndRemove': bool(self.request.GET.get('canAddAndRemove', True)),
            # front end needs this to be able to set the correct
            # api headers for saving subs
            'authHeaders': {
                'x-api-username': self.request.user.username,
                'x-apikey': self.request.user.get_api_key()
            },
            'username': self.request.user.username,
            'video': {
                'id': self.video.video_id,
                'title': self.video.title,
                'description': self.video.description,
                'primaryVideoURL': self.video.get_video_url(),
                'videoURLs': self.get_video_urls(),
                'metadata': self.video.get_metadata(),
            },
            'editingVersion': {
                'languageCode': self.editing_language.language_code,
                'versionNumber': (self.editing_version.version_number
                                  if self.editing_version else None),
            },
            'baseLanguage': self.base_language,
            'languages': [self.editor_data_for_language(lang)
                          for lang in self.languages],
            'languageCode': self.request.LANGUAGE_CODE,
            'oldEditorURL': reverse('subtitles:old-editor', kwargs={
                'video_id': self.video.video_id,
                'language_code': self.editing_language.language_code,
            }),
            'preferences': {
                'showTutorial': self.request.user.show_tutorial,
            },
            'staticURL': settings.STATIC_URL,
            'notesHeading': 'Editor Notes',
            'redirectUrl': self.get_redirect_url(),
            'customCss': self.get_custom_css(),
        }

        editor_data.update(self.workflow.editor_data(
            self.user, self.language_code))

        team_attributes = self.get_team_editor_data()
        if team_attributes:
            editor_data['teamAttributes'] = team_attributes

        return editor_data

    def editor_data_for_language(self, language):
        versions_data = []

        if self.workflow.user_can_view_private_subtitles(
            self.user, language.language_code):
            language_qs = language.subtitleversion_set.extant()
        else:
            language_qs = language.subtitleversion_set.public()
        for i, version in enumerate(language_qs):
            version_data = {
                'version_no':version.version_number,
                'visibility': visibility(version),
            }
            if self.editing_version == version:
                version_data.update(_version_data(version))
            elif self.translated_from_version == version:
                version_data.update(_version_data(version))
            elif (language.language_code == self.base_language and
                  i == len(language_qs) - 1):
                version_data.update(_version_data(version))

            versions_data.append(version_data)


        return {
            'translatedFrom': self.translated_from_version and {
                'language_code': self.translated_from_version.subtitle_language.language_code,
                'version_number': self.translated_from_version.version_number,
            },
            'editingLanguage': language == self.editing_language,
            'language_code': language.language_code,
            'name': language.get_language_code_display(),
            'pk': language.pk,
            'numVersions': language.num_versions,
            'versions': versions_data,
            'subtitles_complete': language.subtitles_complete,
            'is_rtl': language.is_rtl(),
            'is_original': language.is_primary_audio_language()
        }

    def get_team_editor_data(self):
        if self.team_video:
            team = self.team_video.team
            return dict([('teamName', team.name), ('type', team.workflow_type), ('guidelines', dict(
                [(s.key_name.split('_', 1)[-1],
                  linebreaks(urlize(force_escape(s.data))))
                 for s in team.settings.guidelines()
                 if s.data.strip()]))])
        else:
            return None

    def assign_task_for_editor(self):
        """Try to assign any unassigned tasks to our user.

        If we can't assign the task, return False.
        """
        if self.team_video is None:
            return True
        task_set = self.team_video.task_set.incomplete().filter(
            language=self.language_code)
        tasks = list(task_set[:1])
        if tasks:
            task = tasks[0]
            if task.assignee is None and can_assign_task(task, self.user):
                task.assignee = self.user
                task.set_expiration()
                task.save()

            if task.assignee != self.user:
                msg = fmt(_("Another user is currently performing "
                            "the %(task_type)s task for these subtitles"),
                          task_type=task.get_type_display())
                messages.error(self.request, msg)
                return False
        return True

    def handle_task(self, context, editor_data):
        """Does most of the dirty-work to handle tasks.  """
        context['task'] = None
        if self.team_video is None:
            return

        task = self.team_video.get_task_for_editor(self.language_code)
        if not task:
            return
        context['task'] = task
        editor_data['task_id'] = task.id
        editor_data['savedNotes'] = task.body
        editor_data['task_needs_pane'] = task.get_type_display() in ('Review', 'Approve')
        editor_data['team_slug'] = task.team.slug
        editor_data['oldEditorURL'] += '?' + urlencode({
            'mode': Task.TYPE_NAMES[task.type].lower(),
            'task_id': task.id,
        })

    def get(self, request, video_id, language_code):
        self.video = get_object_or_404(Video, video_id=video_id)
        self.team_video = self.video.get_team_video()
        self.language_code = language_code
        self.user = request.user
        self.calc_base_language()
        self.calc_editing_language()
        self.workflow = get_workflow(self.video)

        if (not self.check_can_edit() or
            not self.check_can_writelock() or
            not self.assign_task_for_editor()):
            return redirect(self.video)

        self.editing_language.writelock(self.user, self.request.browser_id,
                                        save=True)
        self.editing_version = self.editing_language.get_tip(public=False)
        # we ignore forking because even if it *is* a fork, we still want to
        # show the user the rererence languages:
        self.translated_from_version = self.editing_language.\
            get_translation_source_version(ignore_forking=True)
        self.languages = self.video.newsubtitlelanguage_set.annotate(
            num_versions=Count('subtitleversion'))
        editor_data = self.get_editor_data()

        context = {
            'title': self.get_title(),
            'video': self.video,
            'DEBUG': settings.DEBUG,
            'language': self.editing_language,
            'other_languages': self.languages,
            'version': self.editing_version,
            'translated_from_version': self.translated_from_version,
            'GOOGLE_ANALYTICS_ADDITIONS': self.get_analytics_additions(),
            'upload_subtitles_form': SubtitlesUploadForm(
                request.user, self.video,
                initial={'language_code':
                         self.editing_language.language_code},
                allow_all_languages=True),
        }
        self.handle_task(context, editor_data)
        context['editor_data'] = json.dumps(editor_data, indent=4)

        return render(request, "editor/editor.html", context)
Beispiel #8
0
 def calc_editing_language(self):
     self.editing_language = self.video.subtitle_language(self.language_code)
     if self.editing_language is None:
         self.editing_language = SubtitleLanguage(
             video=self.video, language_code=self.language_code)
Beispiel #9
0
def make_subtitle_language(video, language_code):
    sl = SubtitleLanguage(video=video, language_code=language_code)
    sl.save()
    return sl
Beispiel #10
0
class SubtitleEditorBase(View):
    def dispatch(self, request, *args, **kwargs):
        self.handle_special_user(request)
        if not request.user.is_authenticated():
            return redirect_to_login(request.build_absolute_uri())
        return super(SubtitleEditorBase,
                     self).dispatch(request, *args, **kwargs)

    def handle_special_user(self, request):
        if 'special_user' not in request.GET:
            return
        try:
            special_user = User.objects.get(
                id=request.session['editor-user-id'])
        except (KeyError, User.DoesNotExist):
            raise PermissionDenied()
        # We use the editor user for this requests, but still don't log them
        # in.  Note that this will also control the auth headers that get sent
        # to the editor, so the API calls will also use this user.
        request.user = special_user

    def get_video_urls(self):
        """Get video URLs to send to the editor."""
        return self.workflow.editor_video_urls(self.language_code)

    def get_redirect_url(self):
        if 'return_url' in self.request.GET:
            return self.request.GET['return_url']
        url = self.editing_language.get_absolute_url()
        if 'team' in self.request.GET:
            url += '?{}'.format(urlencode({'team': self.request.GET['team']}))
        return url

    def get_custom_css(self):
        return ""

    def get_title(self):
        if self.experimental:
            return _('Amara - Experimental')
        else:
            return _('Amara')

    def calc_base_language(self):
        if (self.video.primary_audio_language_code
                and SubtitleVersion.objects.extant().filter(
                    video=self.video,
                    language_code=self.video.primary_audio_language_code).
                exists()):
            self.base_language = self.video.primary_audio_language_code
        else:
            self.base_language = None

    def calc_editing_language(self):
        self.editing_language = self.video.subtitle_language(
            self.language_code)
        if self.editing_language is None:
            self.editing_language = SubtitleLanguage(
                video=self.video, language_code=self.language_code)

    def check_can_writelock(self):
        if not self.editing_language.can_writelock(self.request.user):
            msg = _(
                "Sorry, you cannot edit these subtitles now because they are being edited by another user. Please check back later."
            )
            messages.error(self.request, msg)
            return False
        else:
            return True

    def check_can_edit(self):
        if self.workflow.user_can_edit_subtitles(self.user,
                                                 self.language_code):
            return True
        learn_more_link = u'<a href="{}">{}</a>'.format(
            u'https://support.amara.org/solution/articles/212109-why-do-i-see-a-message-saying-that-i-am-not-permitted-to-edit-subtitles',
            _(u'Learn more'))

        messages.error(
            self.request,
            fmt(_('Sorry, you do not have permission to edit '
                  'these subtitles. (%(learn_more_link)s)'),
                learn_more_link=learn_more_link))
        return False

    def get_editor_data(self):
        editor_data = {
            'canSync':
            bool(self.request.GET.get('canSync', True)),
            'canAddAndRemove':
            bool(self.request.GET.get('canAddAndRemove', True)),
            # front end needs this to be able to set the correct
            # api headers for saving subs
            'authHeaders': {
                'x-api-username': self.request.user.username,
                'x-apikey': self.request.user.get_api_key()
            },
            'username':
            self.request.user.username,
            'user_fullname':
            unicode(self.request.user),
            'video': {
                'id':
                self.video.video_id,
                'title':
                self.video.title,
                'description':
                self.video.description,
                'duration':
                self.video.duration,
                'primaryVideoURLType':
                video_type_registrar.video_type_for_url(
                    self.video.get_video_url()).abbreviation,
                'videoURLs':
                self.get_video_urls(),
                'metadata':
                self.video.get_metadata(),
            },
            'editingVersion': {
                'languageCode':
                self.editing_language.language_code,
                'versionNumber': (self.editing_version.version_number
                                  if self.editing_version else None),
            },
            'baseLanguage':
            self.base_language,
            'languages':
            [self.editor_data_for_language(lang) for lang in self.languages],
            'languageCode':
            self.request.LANGUAGE_CODE,
            'oldEditorURL':
            reverse('subtitles:old-editor',
                    kwargs={
                        'video_id': self.video.video_id,
                        'language_code': self.editing_language.language_code,
                    }),
            'playbackModes':
            self.get_editor_data_for_playback_modes(),
            'preferences': {
                'showTutorial': self.request.user.show_tutorial,
                'playbackModeId': self.request.user.playback_mode
            },
            'staticURL':
            settings.STATIC_URL,
            'notesHeading':
            'Editor Notes',
            'notesEnabled':
            True,
            'redirectUrl':
            self.get_redirect_url(),
            'customCss':
            self.get_custom_css(),
        }

        editor_data.update(
            self.workflow.editor_data(self.user, self.language_code))

        team_attributes = self.get_team_editor_data()
        if team_attributes:
            editor_data['teamAttributes'] = team_attributes

        return editor_data

    def editor_data_for_language(self, language):
        versions_data = []

        if self.workflow.user_can_view_private_subtitles(
                self.user, language.language_code):
            language_qs = language.subtitleversion_set.extant()
        else:
            language_qs = language.subtitleversion_set.public()
        for i, version in enumerate(language_qs):
            version_data = {
                'version_no': version.version_number,
                'visibility': visibility(version),
            }
            if self.editing_version == version:
                version_data.update(_version_data(version))
            elif self.translated_from_version == version:
                version_data.update(_version_data(version))
            elif (language.language_code == self.base_language
                  and i == len(language_qs) - 1):
                version_data.update(_version_data(version))

            versions_data.append(version_data)

        return {
            'translatedFrom': self.translated_from_version and {
                'language_code':
                self.translated_from_version.subtitle_language.language_code,
                'version_number': self.translated_from_version.version_number,
            },
            'editingLanguage': language == self.editing_language,
            'language_code': language.language_code,
            'name': language.get_language_code_display(),
            'pk': language.pk,
            'numVersions': language.num_versions,
            'versions': versions_data,
            'subtitles_complete': language.subtitles_complete,
            'is_rtl': language.is_rtl(),
            'is_original': language.is_primary_audio_language()
        }

    def get_editor_data_for_playback_modes(self):
        return [{
            'id':
            User.PLAYBACK_MODE_MAGIC,
            'idStr':
            'magic',
            'name':
            _('Magic'),
            'desc':
            _('Recommended: magical auto-pause (just keep typing!)')
        }, {
            'id': User.PLAYBACK_MODE_STANDARD,
            'idStr': 'standard',
            'name': _('Standard'),
            'desc': _('Standard: no automatic pausing, use TAB key')
        }, {
            'id': User.PLAYBACK_MODE_BEGINNER,
            'idStr': 'beginner',
            'name': _('Beginner'),
            'desc': _('Beginner: play 4 seconds, then pause')
        }]

    def get_team_editor_data(self):
        if self.team_video:
            team = self.team_video.team
            return dict([('teamName', team.name), ('type', team.workflow_type),
                         ('features', [
                             f.key_name.split('_', 1)[-1]
                             for f in team.settings.features()
                         ]),
                         ('guidelines',
                          dict([(s.key_name.split('_', 1)[-1],
                                 linebreaks(urlize(force_escape(s.data))))
                                for s in team.settings.guidelines()
                                if s.data.strip()]))])
        else:
            return None

    def assign_task_for_editor(self):
        """Try to assign any unassigned tasks to our user.

        If we can't assign the task, return False.
        """
        if self.team_video is None:
            return True
        task_set = self.team_video.task_set.incomplete().filter(
            language=self.language_code)
        tasks = list(task_set[:1])
        if tasks:
            task = tasks[0]
            if task.assignee is None and can_perform_task(self.user, task):
                task.assignee = self.user
                task.set_expiration()
                task.save()

            if task.assignee != self.user:
                msg = fmt(_("Another user is currently performing "
                            "the %(task_type)s task for these subtitles"),
                          task_type=task.get_type_display())
                messages.error(self.request, msg)
                return False
        return True

    def handle_task(self, context, editor_data):
        """Does most of the dirty-work to handle tasks.  """
        context['task'] = None
        if self.team_video is None:
            return

        task = self.team_video.get_task_for_editor(self.language_code)
        if not task:
            return
        context['task'] = task
        editor_data['task_id'] = task.id
        editor_data['savedNotes'] = task.body
        editor_data['task_needs_pane'] = task.get_type_display() in ('Review',
                                                                     'Approve')
        editor_data['team_slug'] = task.team.slug
        editor_data['oldEditorURL'] += '?' + urlencode(
            {
                'mode': Task.TYPE_NAMES[task.type].lower(),
                'task_id': task.id,
            })

    def get(self, request, video_id, language_code):
        self.video = get_object_or_404(Video, video_id=video_id)
        self.team_video = self.video.get_team_video()
        self.language_code = language_code
        self.user = request.user
        self.calc_base_language()
        self.calc_editing_language()
        self.workflow = get_workflow(self.video)

        if (not self.check_can_edit() or not self.check_can_writelock()
                or not self.assign_task_for_editor()):
            if 'team' in self.request.GET:
                qs = '?{}'.format(urlencode({'team':
                                             self.request.GET['team']}))
                return redirect(self.video.get_absolute_url() + qs)
            return redirect(self.video)

        self.editing_language.writelock(self.user, save=True)
        self.editing_version = self.editing_language.get_tip(public=False)
        # we ignore forking because even if it *is* a fork, we still want to
        # show the user the rererence languages:
        self.translated_from_version = self.editing_language.\
            get_translation_source_version(ignore_forking=True)
        self.languages = self.video.newsubtitlelanguage_set.annotate(
            num_versions=Count('subtitleversion'))
        editor_data = self.get_editor_data()
        self.experimental = 'experimental' in request.GET

        context = {
            'title':
            self.get_title(),
            'video':
            self.video,
            'DEBUG':
            settings.DEBUG,
            'language':
            self.editing_language,
            'other_languages':
            self.languages,
            'version':
            self.editing_version,
            'translated_from_version':
            self.translated_from_version,
            'experimental':
            self.experimental,
            'upload_subtitles_form':
            SubtitlesUploadForm(
                request.user,
                self.video,
                initial={'language_code': self.editing_language.language_code},
                allow_all_languages=True),
        }
        self.handle_task(context, editor_data)
        context['editor_data'] = json.dumps(editor_data, indent=4)

        if self.experimental:
            return render(request, "experimental-editor/editor.html", context)
        else:
            return render(request, "editor/editor.html", context)
Beispiel #11
0
    def test_email_diff_subtitles(self):
        initial_count = len(mail.outbox)
        # set a user who can receive notification
        # make sure we have a different author, else he won't get notified
        author = User(username='******',
                      email='*****@*****.**',
                      notify_by_email=True,
                      valid_email=True)
        author.save(send_email_confirmation=False)
        # bypass logic from hell
        author.valid_email = True
        author.save()

        # this is needed for the non_editor template check
        user2 = User(username='******',
                     email='*****@*****.**',
                     notify_by_email=True,
                     valid_email=True)
        user2.save(send_email_confirmation=False)
        # bypass logic from hell
        user2.valid_email = True
        user2.save()
        # version is indentical to previous one
        video, video_url = Video.add("http://wwww.example.com/video-diff.mp4",
                                     None)
        video.followers.add(author)
        video.followers.add(user2)

        language = SubtitleLanguage(video=video, language_code='en')
        language.save()
        subs_data = [
            [0, 1000, '1'],
            [1000, 2000, '2'],
        ]

        subtitles_1 = SubtitleSet.from_list('en', subs_data)
        old_version = language.add_version(subtitles=subtitles_1,
                                           author=author)

        # now we change the text on the second sub
        subs_data[1][2] = '2 changed'
        # add a regular sub
        subs_data.append([2000, 3000, 'new sub'])
        # add an unsyced
        subs_data.append([None, None, 'no sync'])
        subtitles_2 = SubtitleSet.from_list('en', subs_data)
        new_version = language.add_version(subtitles=subtitles_2)
        self.assertTrue(len(video.notification_list()) > 0)

        res = send_new_version_notification(new_version.pk)
        self.assertNotEqual(res, None)
        # we expect two emails, one is the new-edits-non-editor, and
        # the other for mail_notification.html
        self.assertEqual(len(mail.outbox), initial_count + 2)
        for email_number, email_msg in enumerate(mail.outbox):
            # make sure this is the right message
            self.assertIn("New edits to ", email_msg.subject)
            self.assertIn("video-diff.mp4", email_msg.subject)
            html = BeautifulSoup(email_msg.body)
            html_text = "".join(html.body(text=True)).replace("\n", "")
            if email_number == 0:
                # assert text and timing changes are correct
                self.assertIn('67% of the text', html_text)
                self.assertIn('33% of the timing was changed.', html_text)
            # find the listed text changes to make sure they match
            diff_table = html.findAll('table', attrs={'class': 'diffs'})[0]
            old_version_changes = []
            new_version_changes = []
            for i, node in enumerate(diff_table.findAll('td')):
                if i % 2 == 0:
                    old_version_changes.append(node.text)
                else:
                    new_version_changes.append(node.text)
            self.assertEqual(old_version_changes, [u'2', u'', u''])
            self.assertEqual(new_version_changes, [
                u'2 changed',
                u'new sub',
                u'no sync',
            ])
Beispiel #12
0
def subtitle_editor(request, video_id, language_code):
    '''
    Renders the subtitle-editor page, with all data neeeded for the UI
    as a json object on the html document.
    If the language does not exist, it will create one and lock it.
    Also decides what source version should be shown initially (if
    it is a translation).
    '''
    # FIXME: permissions
    video = get_object_or_404(Video, video_id=video_id)

    if (video.primary_audio_language_code
            and SubtitleVersion.objects.extant().filter(
                video=video,
                language_code=video.primary_audio_language_code).exists()):
        base_language = video.primary_audio_language_code
    else:
        base_language = None

    try:
        editing_language = video.newsubtitlelanguage_set.get(
            language_code=language_code)
    except SubtitleLanguage.DoesNotExist:
        editing_language = SubtitleLanguage(video=video,
                                            language_code=language_code)

    if not editing_language.can_writelock(request.browser_id):
        messages.error(request,
                       _("You can't edit this subtitle because it's locked"))
        return redirect(video)

    error_message = assign_task_for_editor(video, language_code, request.user)
    if error_message:
        messages.error(request, error_message)
        return redirect(video)
    task = get_task_for_editor(video, language_code)
    check_result = can_add_version(request.user, video, language_code)
    if not check_result:
        messages.error(request, check_result.message)
        return redirect(video)

    editing_language.writelock(request.user, request.browser_id, save=True)

    # if this language is a translation, show both
    editing_version = editing_language.get_tip(public=False)
    # we ignore forking because even if it *is* a fork, we still want to show
    # the user the rererence languages:
    translated_from_version = editing_language.\
        get_translation_source_version(ignore_forking=True)

    languages = video.newsubtitlelanguage_set.annotate(
        num_versions=Count('subtitleversion'))

    video_urls = []
    for v in video.get_video_urls():
        video_urls.append(v.url)

    editor_data = {
        'canSync':
        bool(request.GET.get('canSync', True)),
        'canAddAndRemove':
        bool(request.GET.get('canAddAndRemove', True)),
        # front end needs this to be able to set the correct
        # api headers for saving subs
        'authHeaders': {
            'x-api-username': request.user.username,
            'x-apikey': request.user.get_api_key()
        },
        'video': {
            'id': video.video_id,
            'title': video.title,
            'description': video.description,
            'primaryVideoURL': video.get_video_url(),
            'videoURLs': video_urls,
            'metadata': video.get_metadata(),
        },
        'editingVersion': {
            'languageCode':
            editing_language.language_code,
            'versionNumber':
            (editing_version.version_number if editing_version else None),
        },
        'baseLanguage':
        base_language,
        'languages': [
            _language_data(lang, editing_version, translated_from_version,
                           base_language) for lang in languages
        ],
        'languageCode':
        request.LANGUAGE_CODE,
        'oldEditorURL':
        reverse('subtitles:old-editor',
                kwargs={
                    'video_id': video.video_id,
                    'language_code': editing_language.language_code,
                }),
        'staticURL':
        settings.STATIC_URL,
    }

    if task:
        editor_data['task_id'] = task.id
        editor_data['savedNotes'] = task.body
        editor_data['task_needs_pane'] = task.get_type_display() in ('Review',
                                                                     'Approve')
        editor_data['team_slug'] = task.team.slug
        editor_data['oldEditorURL'] += '?' + urlencode(
            {
                'mode': Task.TYPE_NAMES[task.type].lower(),
                'task_id': task.id,
            })

    team_attributes = get_team_attributes_for_editor(video)
    if team_attributes:
        editor_data['teamAttributes'] = team_attributes

    return render_to_response("subtitles/subtitle-editor.html", {
        'video': video,
        'DEBUG': settings.DEBUG,
        'language': editing_language,
        'other_languages': languages,
        'version': editing_version,
        'translated_from_version': translated_from_version,
        'task': task,
        'editor_data': json.dumps(editor_data, indent=4)
    },
                              context_instance=RequestContext(request))
Beispiel #13
0
 def create(self, validated_data):
     language = SubtitleLanguage(
         video=self.context['video'],
         language_code=validated_data['language_code'])
     return self.update(language, validated_data)