Exemplo n.º 1
0
def vidly_media_webhook(request):
    if not request.POST.get('xml'):
        return http.HttpResponseBadRequest("no 'xml'")

    xml_string = request.POST['xml'].strip()
    try:
        struct = xmltodict.parse(xml_string)
    except ExpatError:
        return http.HttpResponseBadRequest("Bad 'xml'")

    try:
        task = struct['Response']['Result']['Task']
        try:
            vidly_submission = VidlySubmission.objects.get(
                url=task['SourceFile'],
                tag=task['MediaShortLink']
            )
            if task['Status'] == 'Finished':
                if not vidly_submission.finished:
                    vidly_submission.finished = timezone.now()
                    vidly_submission.save()

                event = vidly_submission.event

                # Awesome!
                # This event now has a fully working transcoded piece of
                # media.
                event.archive_time = timezone.now()
                event.save()

                # More awesome! We can start processing the transcoded media.
                if not event.duration:
                    videoinfo.fetch_duration(
                        event,
                        save=True,
                        verbose=settings.DEBUG
                    )
                    event = Event.objects.get(id=event.id)
                if event.duration:
                    if not Picture.objects.filter(event=event):
                        videoinfo.fetch_screencapture(
                            event,
                            save=True,
                            verbose=settings.DEBUG,
                            set_first_available=True,
                        )
            elif task['Status'] == 'Error':
                if not vidly_submission.errored:
                    vidly_submission.errored = timezone.now()
                    vidly_submission.save()
        except VidlySubmission.DoesNotExist:
            # remember, we can't trust the XML since it's publically
            # available and exposed as a webhook
            pass
    except KeyError:
        # If it doesn't have a "Result" or "Task", it was just a notification
        # that the media was added.
        pass

    return http.HttpResponse('OK\n')
Exemplo n.º 2
0
def create_chapterimages(chapter, verbose=False):
    def saved_file(chapter, filepath):
        with open(filepath, 'rb') as fp:
            opened = File(fp)
            chapter.image.save(os.path.basename(filepath), opened, save=True)
            return True

    fetch_screencapture(chapter.event,
                        timestamps=[chapter.timestamp],
                        import_=True,
                        import_immediately=True,
                        verbose=verbose,
                        callback=partial(saved_file, chapter))
Exemplo n.º 3
0
def create_all_event_pictures(
    event_id,
    set_first_available=False,
    video_url=None,
):
    event = Event.objects.get(id=event_id)
    videoinfo.fetch_screencapture(
        event,
        save=True,
        video_url=video_url,
        verbose=settings.DEBUG,
        set_first_available=set_first_available,
    )
Exemplo n.º 4
0
def create_timestamp_pictures(
    event,
    timestamps,
    verbose=False,
    video_url=None
):
    fetch_screencapture(
        event,
        timestamps=timestamps,
        import_=True,
        import_immediately=True,
        verbose=verbose,
        video_url=video_url,
    )
Exemplo n.º 5
0
def event_screencaptures(request, event):
    if event.status != Event.STATUS_INITIATED:
        return http.HttpResponseBadRequest(
            "Events NOT in the state of initiated."
        )
    upload = event.upload
    video_url = upload.url

    context = {}

    cache_key = 'fetching-{0}'.format(event.id)

    # This function sets the cache `fetching-{id}` before and after calling
    # those functions in the videoinfo module.
    # The reason is that those calls might take many many seconds
    # and the webapp might send async calls to the event_picture view
    # which will inform the webapp that the slow videoinfo processes
    # are running and thus that the webapp shouldn't kick if off yet.

    seconds = event.duration
    if not event.duration:
        # it's a poor man's lock
        if not cache.get(cache_key):
            cache.set(cache_key, True, 60)
            seconds = videoinfo.fetch_duration(
                event,
                video_url=video_url,
                save=True,
                verbose=settings.DEBUG
            )
            cache.delete(cache_key)
            event = Event.objects.get(id=event.id)
    context['seconds'] = seconds
    # The reason we can't use `if event.duration:` is because the
    # fetch_duration() does an inline-update instead of modifying
    # the instance object.
    no_pictures = Picture.objects.filter(event=event).count()
    if event.duration and not no_pictures:
        if not cache.get(cache_key):
            cache.set(cache_key, True, 60)
            event = Event.objects.get(id=event.id)
            no_pictures = videoinfo.fetch_screencapture(
                event,
                video_url=video_url,
                save=True,
                verbose=settings.DEBUG,
                set_first_available=not event.picture,
                import_immediately=True,
            )
            cache.delete(cache_key)
            event = Event.objects.get(id=event.id)
    if no_pictures and not event.picture:
        # no picture has been chosen previously
        pictures = Picture.objects.filter(event=event).order_by('created')[:1]
        for picture in pictures:
            event.picture = picture
            event.save()
            break
    context['no_pictures'] = no_pictures
    return context
Exemplo n.º 6
0
def create_chapterimages(chapter, verbose=False):

    def saved_file(chapter, filepath):
        with open(filepath, 'rb') as fp:
            opened = File(fp)
            chapter.image.save(os.path.basename(filepath), opened, save=True)
            return True

    fetch_screencapture(
        chapter.event,
        timestamps=[chapter.timestamp],
        import_=True,
        import_immediately=True,
        verbose=verbose,
        callback=partial(saved_file, chapter)
    )
Exemplo n.º 7
0
def event_screencaptures(request, event):
    if event.status != Event.STATUS_INITIATED:
        return http.HttpResponseBadRequest(
            "Events NOT in the state of initiated."
        )
    upload = event.upload
    video_url = upload.url

    context = {}

    cache_key = 'fetching-{0}'.format(event.id)

    # This function sets the cache `fetching-{id}` before and after calling
    # those functions in the videoinfo module.
    # The reason is that those calls might take many many seconds
    # and the webapp might send async calls to the event_picture view
    # which will inform the webapp that the slow videoinfo processes
    # are running and thus that the webapp shouldn't kick if off yet.

    seconds = event.duration
    if not event.duration:
        # it's a poor man's lock
        if not cache.get(cache_key):
            cache.set(cache_key, True, 60)
            seconds = videoinfo.fetch_duration(
                event,
                video_url=video_url,
                save=True,
                verbose=settings.DEBUG
            )
            cache.delete(cache_key)
            event = Event.objects.get(id=event.id)
    context['seconds'] = seconds
    # The reason we can't use `if event.duration:` is because the
    # fetch_duration() does an inline-update instead of modifying
    # the instance object.
    no_pictures = Picture.objects.filter(event=event).count()
    if event.duration and not no_pictures:
        if not cache.get(cache_key):
            cache.set(cache_key, True, 60)
            event = Event.objects.get(id=event.id)
            no_pictures = videoinfo.fetch_screencapture(
                event,
                video_url=video_url,
                save=True,
                verbose=settings.DEBUG,
                set_first_available=not event.picture,
                import_immediately=True,
            )
            cache.delete(cache_key)
            event = Event.objects.get(id=event.id)
    if no_pictures and not event.picture:
        # no picture has been chosen previously
        pictures = Picture.objects.filter(event=event).order_by('created')[:1]
        for picture in pictures:
            event.picture = picture
            event.save()
            break
    context['no_pictures'] = no_pictures
    return context
Exemplo n.º 8
0
    def test_fetch_screencapture_set_first_available(
        self, mock_popen, rhead, p_urllib2
    ):
        assert Picture.objects.all().count() == 0, Picture.objects.all()

        def mocked_urlopen(request):
            return StringIO("""
            <?xml version="1.0"?>
            <Response>
              <Message>OK</Message>
              <MessageCode>7.4</MessageCode>
              <Success>
                <MediaShortLink>xxx999</MediaShortLink>
                <Token>MXCsxINnVtycv6j02ZVIlS4FcWP</Token>
              </Success>
            </Response>
            """)

        p_urllib2.urlopen = mocked_urlopen

        def mocked_head(url, **options):
            return Response(
                '',
                200
            )

        rhead.side_effect = mocked_head

        ffmpeged_urls = []

        sample_jpg = self.sample_jpg
        sample_jpg2 = self.sample_jpg2

        def mocked_popen(command, **kwargs):
            url = command[4]
            ffmpeged_urls.append(url)
            destination = command[-1]
            assert os.path.isdir(os.path.dirname(destination))

            class Inner:
                def communicate(self):
                    out = err = ''
                    if 'xyz123' in url:
                        if '01.jpg' in destination:
                            shutil.copyfile(sample_jpg, destination)
                        else:
                            shutil.copyfile(sample_jpg2, destination)
                    else:
                        raise NotImplementedError(url)
                    return out, err

            return Inner()

        mock_popen.side_effect = mocked_popen

        event = Event.objects.get(title='Test event')
        template = Template.objects.create(
            name='Vid.ly Something',
            content="{{ tag }}"
        )
        event.template = template
        event.duration = 1157
        event.save()

        # Make sure it has a HD VidlySubmission
        VidlySubmission.objects.create(
            event=event,
            url='https://s3.com/asomething.mov',
            tag='xyz123',
            hd=True,
        )
        event.template_environment = {'tag': 'xyz123'}
        event.save()
        videoinfo.fetch_screencapture(event, set_first_available=True)
        assert ffmpeged_urls
        no_screencaptures = settings.SCREENCAPTURES_NO_PICTURES
        pictures = Picture.objects.filter(event=event)
        eq_(pictures.count(), no_screencaptures)
        event = Event.objects.get(id=event.id)
        eq_(event.picture, pictures.order_by('created')[0])
Exemplo n.º 9
0
    def test_fetch_screencapture_set_first_available(self, mock_popen, rhead,
                                                     p_urllib2):
        assert Picture.objects.all().count() == 0, Picture.objects.all()

        def mocked_urlopen(request):
            return StringIO("""
            <?xml version="1.0"?>
            <Response>
              <Message>OK</Message>
              <MessageCode>7.4</MessageCode>
              <Success>
                <MediaShortLink>xxx999</MediaShortLink>
                <Token>MXCsxINnVtycv6j02ZVIlS4FcWP</Token>
              </Success>
            </Response>
            """)

        p_urllib2.urlopen = mocked_urlopen

        def mocked_head(url, **options):
            return Response('', 200)

        rhead.side_effect = mocked_head

        ffmpeged_urls = []

        sample_jpg = self.sample_jpg
        sample_jpg2 = self.sample_jpg2

        def mocked_popen(command, **kwargs):
            url = command[4]
            ffmpeged_urls.append(url)
            destination = command[-1]
            assert os.path.isdir(os.path.dirname(destination))

            class Inner:
                def communicate(self):
                    out = err = ''
                    if 'xyz123' in url:
                        if '01.jpg' in destination:
                            shutil.copyfile(sample_jpg, destination)
                        else:
                            shutil.copyfile(sample_jpg2, destination)
                    else:
                        raise NotImplementedError(url)
                    return out, err

            return Inner()

        mock_popen.side_effect = mocked_popen

        event = Event.objects.get(title='Test event')
        template = Template.objects.create(name='Vid.ly Something',
                                           content="{{ tag }}")
        event.template = template
        event.duration = 1157
        event.save()

        # Make sure it has a HD VidlySubmission
        VidlySubmission.objects.create(
            event=event,
            url='https://s3.com/asomething.mov',
            tag='xyz123',
            hd=True,
        )
        event.template_environment = {'tag': 'xyz123'}
        event.save()
        videoinfo.fetch_screencapture(event, set_first_available=True)
        assert ffmpeged_urls
        no_screencaptures = settings.SCREENCAPTURES_NO_PICTURES
        pictures = Picture.objects.filter(event=event)
        eq_(pictures.count(), no_screencaptures)
        event = Event.objects.get(id=event.id)
        eq_(event.picture, pictures.order_by('created')[0])
Exemplo n.º 10
0
    def test_fetch_screencapture_at_timestamp_with_callback(
        self, mock_popen, rhead, p_urllib2, p_log
    ):
        """This test is effectively the same as test_fetch_screencapture()
        but with `import_immediately=True` set.
        """
        def mocked_urlopen(request):
            return StringIO("""
            <?xml version="1.0"?>
            <Response>
              <Message>OK</Message>
              <MessageCode>7.4</MessageCode>
              <Success>
                <MediaShortLink>xxx999</MediaShortLink>
                <Token>MXCsxINnVtycv6j02ZVIlS4FcWP</Token>
              </Success>
            </Response>
            """)

        p_urllib2.urlopen = mocked_urlopen

        def mocked_head(url, **options):
            return Response(
                '',
                200
            )

        rhead.side_effect = mocked_head

        ffmpeged_urls = []

        sample_jpg = self.sample_jpg
        sample_jpg2 = self.sample_jpg2

        def mocked_popen(command, **kwargs):
            url = command[4]
            ffmpeged_urls.append(url)
            destination = command[-1]
            assert os.path.isdir(os.path.dirname(destination))

            class Inner:
                def communicate(self):
                    out = err = ''
                    if 'xyz123' in url:
                        # Let's create two jpeg's in that directory
                        if '01.jpg' in destination:
                            shutil.copyfile(sample_jpg, destination)
                        else:
                            shutil.copyfile(sample_jpg2, destination)
                    else:
                        raise NotImplementedError(url)
                    return out, err

            return Inner()

        mock_popen.side_effect = mocked_popen

        event = Event.objects.get(title='Test event')
        template = Template.objects.create(
            name='Vid.ly Something',
            content="{{ tag }}"
        )
        event.duration = 1157
        event.template = template
        event.save()

        # Make sure it has a HD VidlySubmission
        VidlySubmission.objects.create(
            event=event,
            url='https://s3.com/asomething.mov',
            tag='xyz123',
            hd=True,
        )
        event.template_environment = {'tag': 'xyz123'}
        event.save()

        def callback(filepath):
            ok_(os.path.isfile(filepath))
            return filepath.endswith('3.jpg')

        created = videoinfo.fetch_screencapture(
            event,
            timestamps=[3],
            callback=callback
        )
        eq_(created, 1)
        eq_(len(ffmpeged_urls), 1)

        created = videoinfo.fetch_screencapture(
            event,
            timestamps=[2],  # callback will return False for this
            callback=callback
        )
        eq_(created, 0)
        eq_(len(ffmpeged_urls), 2)
Exemplo n.º 11
0
def vidly_media_webhook(request):
    if not request.POST.get('xml'):
        return http.HttpResponseBadRequest("no 'xml'")

    xml_string = request.POST['xml'].strip()
    try:
        struct = xmltodict.parse(xml_string)
    except ExpatError:
        return http.HttpResponseBadRequest("Bad 'xml'")

    try:
        task = struct['Response']['Result']['Task']
        try:
            vidly_submission = VidlySubmission.objects.get(
                url=task['SourceFile'], tag=task['MediaShortLink'])
            if task['Status'] == 'Finished':
                if not vidly_submission.finished:
                    vidly_submission.finished = timezone.now()
                    vidly_submission.save()

                event = vidly_submission.event

                if (task['Private'] == 'false'
                        and event.privacy != Event.PRIVACY_PUBLIC):
                    # the event is private but the video is not
                    vidly.update_media_protection(
                        vidly_submission.tag,
                        True  # make it private
                    )
                    if not vidly_submission.token_protection:
                        vidly_submission.token_protection = True
                        vidly_submission.save()

                # Awesome!
                # This event now has a fully working transcoded piece of
                # media.
                if (event.status == Event.STATUS_PENDING
                        or event.status == Event.STATUS_PROCESSING):
                    event.status = Event.STATUS_SCHEDULED
                event.archive_time = timezone.now()
                event.save()

                # More awesome! We can start processing the transcoded media.
                # XXX move this to a background task.
                if not event.duration:
                    videoinfo.fetch_duration(event,
                                             save=True,
                                             verbose=settings.DEBUG)
                    event = Event.objects.get(id=event.id)
                if event.duration:
                    if not Picture.objects.filter(event=event):
                        videoinfo.fetch_screencapture(
                            event,
                            save=True,
                            verbose=settings.DEBUG,
                            set_first_available=True,
                        )
            elif task['Status'] == 'Error':
                if not vidly_submission.errored:
                    vidly_submission.errored = timezone.now()
                    vidly_submission.save()
        except VidlySubmission.DoesNotExist:
            # remember, we can't trust the XML since it's publicly
            # available and exposed as a webhook
            pass

    except KeyError:
        # If it doesn't have a "Result" or "Task", it was just a notification
        # that the media was added.
        pass

    return http.HttpResponse('OK\n')