Example #1
0
    def test_generate_renditions_custom_crop(self):
        inserted = []
        renditions = get_renditions_spec()
        with open(IMG_PATH, 'rb') as original:
            generated = generate_renditions(original, 'id', inserted, 'image',
                                            'image/jpeg', renditions,
                                            self.app.media.url_for_media)

        # thumbnail should keep 4:3 ration
        self.assertIn('thumbnail', generated)
        self.assertEqual(160, generated['thumbnail']['width'])
        self.assertEqual(120, generated['thumbnail']['height'])

        # landscape should be cropped to 200x100
        self.assertIn('landscape', generated)
        landscape = generated['landscape']
        self.assertEqual(200, landscape['width'])
        self.assertEqual(100, landscape['height'])
        self.assertEqual(0, landscape['CropLeft'])
        self.assertEqual(400, landscape['CropRight'])
        self.assertEqual(50, landscape['CropTop'])
        self.assertEqual(250, landscape['CropBottom'])

        # portrait should be cropped to 150x200
        self.assertIn('portrait', generated)
        portrait = generated['portrait']
        self.assertEqual(150, portrait['width'])
        self.assertEqual(200, portrait['height'])
        self.assertEqual(0, portrait['CropTop'])
        self.assertEqual(300, portrait['CropBottom'])
        self.assertEqual(87, portrait['CropLeft'])
        self.assertEqual(312, portrait['CropRight'])
    def on_create(self, docs):
        ''' Create corresponding item on file upload '''
        for doc in docs:
            file, content_type, metadata = self.get_file_from_document(doc)
            inserted = [doc['media']]
            file_type = content_type.split('/')[0]

            try:
                update_dates_for(doc)
                doc['guid'] = generate_guid(type=GUID_TAG)
                doc.setdefault('_id', doc['guid'])
                doc['type'] = self.type_av.get(file_type)
                doc['version'] = 1
                doc['versioncreated'] = utcnow()
                rendition_spec = config.RENDITIONS['picture']
                renditions = generate_renditions(file, doc['media'], inserted, file_type,
                                                 content_type, rendition_spec, url_for_media)
                doc['renditions'] = renditions
                doc['mimetype'] = content_type
                doc['filemeta'] = metadata
                if not doc.get('_import', None):
                    doc['creator'] = set_user(doc)

                add_activity('uploaded media {{ name }}',
                             name=doc.get('headline', doc.get('mimetype')),
                             renditions=doc.get('renditions'))

            except Exception as io:
                logger.exception(io)
                for file_id in inserted:
                    delete_file_on_error(doc, file_id)
                abort(500)
        on_create_media_archive()
    def on_create(self, docs):
        ''' Create corresponding item on file upload '''
        for doc in docs:
            file, content_type, metadata = self.get_file_from_document(doc)
            inserted = [doc['media']]
            file_type = content_type.split('/')[0]

            try:
                update_dates_for(doc)
                doc['guid'] = generate_guid(type=GUID_TAG)
                doc.setdefault('_id', doc['guid'])
                doc['type'] = self.type_av.get(file_type)
                doc['version'] = 1
                doc['versioncreated'] = utcnow()
                rendition_spec = config.RENDITIONS['picture']
                renditions = generate_renditions(file, doc['media'], inserted, file_type,
                                                 content_type, rendition_spec, url_for_media)
                doc['renditions'] = renditions
                doc['mimetype'] = content_type
                doc['filemeta'] = metadata
                if not doc.get('_import', None):
                    doc['creator'] = set_user(doc)

                add_activity('uploaded media {{ name }}',
                             name=doc.get('headline', doc.get('mimetype')),
                             renditions=doc.get('renditions'))

            except Exception as io:
                logger.exception(io)
                for file_id in inserted:
                    delete_file_on_error(doc, file_id)
                abort(500)
        on_create_media_archive()
Example #4
0
    def store_file(self, doc, content, filename, content_type):
        res = process_file_from_stream(content,
                                       filename=filename,
                                       content_type=content_type)
        file_name, content_type, metadata = res

        cropping_data = self.get_cropping_data(doc)
        _, out = crop_image(content, filename, cropping_data)
        metadata['length'] = json.dumps(len(out.getvalue()))

        try:
            logger.debug('Going to save media file with %s ' % file_name)
            out.seek(0)
            id = app.media.put(out,
                               filename=file_name,
                               content_type=content_type,
                               metadata=metadata)
            doc['media'] = id
            doc['mime_type'] = content_type
            doc['filemeta'] = decode_metadata(metadata)
            inserted = [doc['media']]
            file_type = content_type.split('/')[0]

            rendition_spec = config.RENDITIONS['avatar']
            renditions = generate_renditions(out, doc['media'], inserted,
                                             file_type, content_type,
                                             rendition_spec, url_for_media)
            doc['renditions'] = renditions
        except Exception as io:
            logger.exception(io)
            for file_id in inserted:
                delete_file_on_error(doc, file_id)
            raise SuperdeskError(message='Generating renditions failed')
Example #5
0
 def crop_and_store_file(self, doc, content, filename, content_type):
     # retrieve file name and metadata from file
     file_name, content_type, metadata = process_file_from_stream(
         content, content_type=content_type)
     # crop the file if needed, can change the image size
     was_cropped, out = crop_image(content, filename, doc)
     # the length in metadata could be updated if it was cropped
     if was_cropped:
         file_name, content_type, metadata_after_cropped = process_file_from_stream(
             out, content_type=content_type)
         # when cropped, metadata are reseted. Then we update the previous metadata variable
         metadata['length'] = metadata_after_cropped['length']
     try:
         logger.debug('Going to save media file with %s ' % file_name)
         out.seek(0)
         file_id = app.media.put(out,
                                 filename=file_name,
                                 content_type=content_type,
                                 resource=self.datasource,
                                 metadata=metadata)
         doc['media'] = file_id
         doc['mimetype'] = content_type
         set_filemeta(doc, decode_metadata(metadata))
         inserted = [doc['media']]
         file_type = content_type.split('/')[0]
         rendition_spec = config.RENDITIONS['avatar']
         renditions = generate_renditions(out, file_id, inserted, file_type,
                                          content_type, rendition_spec,
                                          url_for_media)
         doc['renditions'] = renditions
     except Exception as io:
         for file_id in inserted:
             delete_file_on_error(doc, file_id)
         raise SuperdeskApiError.internalError(
             'Generating renditions failed', exception=io)
Example #6
0
    def on_create(self, docs):
        """Create corresponding item on file upload."""

        for doc in docs:
            if 'media' not in doc or doc['media'] is None:
                abort(400, description="No media found")

            file, content_type, metadata = self.get_file_from_document(doc)
            inserted = [doc['media']]
            file_type = content_type.split('/')[0]

            self._set_metadata(doc)

            try:
                doc[ITEM_TYPE] = self.type_av.get(file_type)
                rendition_spec = get_renditions_spec()
                renditions = generate_renditions(file, doc['media'], inserted,
                                                 file_type, content_type,
                                                 rendition_spec, url_for_media)
                doc['renditions'] = renditions
                doc['mimetype'] = content_type
                set_filemeta(doc, metadata)

                add_activity('upload',
                             'uploaded media {{ name }}',
                             'archive',
                             item=doc,
                             name=doc.get('headline', doc.get('mimetype')),
                             renditions=doc.get('renditions'))
            except Exception as io:
                logger.exception(io)
                for file_id in inserted:
                    delete_file_on_error(doc, file_id)
                abort(500)
Example #7
0
 def crop_and_store_file(self, doc, content, filename, content_type):
     # retrieve file name and metadata from file
     file_name, content_type, metadata = process_file_from_stream(content, content_type=content_type)
     # crop the file if needed, can change the image size
     was_cropped, out = crop_image(content, filename, doc)
     # the length in metadata could be updated if it was cropped
     if was_cropped:
         file_name, content_type, metadata_after_cropped = process_file_from_stream(out, content_type=content_type)
         # when cropped, metadata are reseted. Then we update the previous metadata variable
         metadata['length'] = metadata_after_cropped['length']
     try:
         logger.debug('Going to save media file with %s ' % file_name)
         out.seek(0)
         file_id = app.media.put(out, filename=file_name, content_type=content_type,
                                 resource=self.datasource, metadata=metadata)
         doc['media'] = file_id
         doc['mimetype'] = content_type
         doc['filemeta'] = decode_metadata(metadata)
         inserted = [doc['media']]
         file_type = content_type.split('/')[0]
         rendition_spec = config.RENDITIONS['avatar']
         renditions = generate_renditions(out, file_id, inserted, file_type,
                                          content_type, rendition_spec, url_for_media)
         doc['renditions'] = renditions
     except Exception as io:
         logger.exception(io)
         for file_id in inserted:
             delete_file_on_error(doc, file_id)
         raise SuperdeskApiError.internalError('Generating renditions failed')
    def setUp(self):
        super().setUp()
        dirname = os.path.dirname(os.path.realpath(__file__))
        image_path = os.path.normpath(
            os.path.join(dirname, 'fixtures', self.filename))
        content_type = mimetypes.guess_type(image_path)[0]
        guid = utils.generate_guid(type=GUID_TAG)
        self.item = {
            'guid': guid,
            'version': 1,
            '_id': guid,
            ITEM_TYPE: CONTENT_TYPE.PICTURE,
            'mimetype': content_type,
            'versioncreated': datetime.now()
        }

        with open(image_path, 'rb') as f:
            _, content_type, file_metadata = process_file_from_stream(
                f, content_type=content_type)
            f.seek(0)
            file_id = app.media.put(f,
                                    filename=self.filename,
                                    content_type=content_type,
                                    metadata=file_metadata)
            filemeta.set_filemeta(self.item, file_metadata)
            f.seek(0)
            rendition_spec = get_renditions_spec()
            renditions = generate_renditions(f, file_id, [file_id], 'image',
                                             content_type, rendition_spec,
                                             url_for_media)
            self.item['renditions'] = renditions
        archive = get_resource_service('archive')
        archive.post([self.item])
    def setUp(self):
        super().setUp()
        dirname = os.path.dirname(os.path.realpath(__file__))
        image_path = os.path.normpath(os.path.join(dirname, 'fixtures', self.filename))
        content_type = mimetypes.guess_type(image_path)[0]
        guid = utils.generate_guid(type=GUID_TAG)
        self.item = {'guid': guid,
                     'version': 1,
                     '_id': guid,
                     ITEM_TYPE: CONTENT_TYPE.PICTURE,
                     'mimetype': content_type,
                     'versioncreated': datetime.now()
                     }

        with open(image_path, 'rb') as f:
            _, content_type, file_metadata = process_file_from_stream(f, content_type=content_type)
            f.seek(0)
            file_id = app.media.put(f, filename=self.filename, content_type=content_type, metadata=file_metadata)
            filemeta.set_filemeta(self.item, file_metadata)
            f.seek(0)
            rendition_spec = get_renditions_spec()
            renditions = generate_renditions(f, file_id, [file_id], 'image',
                                             content_type, rendition_spec, url_for_media)
            self.item['renditions'] = renditions
        archive = get_resource_service('archive')
        archive.post([self.item])
Example #10
0
    def on_create(self, docs):
        """Create corresponding item on file upload."""

        for doc in docs:
            if 'media' not in doc or doc['media'] is None:
                abort(400, description="No media found")

            file, content_type, metadata = self.get_file_from_document(doc)
            inserted = [doc['media']]
            file_type = content_type.split('/')[0]

            self._set_metadata(doc)

            try:
                doc[ITEM_TYPE] = self.type_av.get(file_type)
                rendition_spec = get_renditions_spec()
                renditions = generate_renditions(file, doc['media'], inserted, file_type,
                                                 content_type, rendition_spec, url_for_media)
                doc['renditions'] = renditions
                doc['mimetype'] = content_type
                set_filemeta(doc, metadata)

                add_activity('upload', 'uploaded media {{ name }}',
                             'archive', item=doc,
                             name=doc.get('headline', doc.get('mimetype')),
                             renditions=doc.get('renditions'))
            except Exception as io:
                logger.exception(io)
                for file_id in inserted:
                    delete_file_on_error(doc, file_id)
                abort(500)
Example #11
0
    def create(self, docs):
        """Apply transformation requested in 'edit'"""
        ids = []
        archive = get_resource_service("archive")
        for doc in docs:
            # first we get item and requested edit operations
            item = doc.pop("item", None)
            if item is None:
                try:
                    item_id = doc.pop("item_id")
                except KeyError:
                    raise errors.SuperdeskApiError.badRequestError(
                        "either item or item_id must be specified")
            else:
                item_id = item[config.ID_FIELD]

            if item is None and item_id:
                item = next(archive.find({"_id": item_id}))
            edit = doc.pop("edit")

            # now we retrieve and load current original media
            rendition = item["renditions"]["original"]
            media_id = rendition["media"]
            media = current_app.media.get(media_id)
            out = im = Image.open(media)

            # we apply all requested operations on original media
            for operation, param in edit.items():
                try:
                    out = self.transform(out, operation, param)
                except ValueError:
                    # if the operation can't be applied just ignore it
                    logger.warning(
                        "failed to apply operation: {operation} {param} for media {id}"
                        .format(operation=operation, param=param, id=media_id))
            buf = BytesIO()
            out.save(buf, format=im.format)

            # we set metadata
            buf.seek(0)
            content_type = rendition["mimetype"]
            ext = os.path.splitext(rendition["href"])[1]
            filename = str(uuid.uuid4()) + ext

            # and save transformed media in database
            media_id = current_app.media.put(buf,
                                             filename=filename,
                                             content_type=content_type)

            # now we recreate other renditions based on transformed original media
            buf.seek(0)
            renditions = generate_renditions(buf, media_id, [],
                                             "image", content_type,
                                             get_renditions_spec(),
                                             current_app.media.url_for_media)

            ids.append(item_id)
            doc["renditions"] = renditions

        return [ids]
Example #12
0
 def upload_fixture_image(
     self, fixture_image_path,
     verification_stats_path, verification_result_path, headline='test'
 ):
     with self.app.app_context():
         with open(fixture_image_path, mode='rb') as f:
             file_name = ntpath.basename(fixture_image_path)
             file_type = 'image'
             content_type = '%s/%s' % (file_type, imghdr.what(f))
             file_id = app.media.put(
                 f, filename=file_name,
                 content_type=content_type,
                 resource=get_resource_service('ingest').datasource,
                 metadata={}
             )
             inserted = [file_id]
             renditions = generate_renditions(
                 f, file_id, inserted, file_type, content_type,
                 rendition_config=config.RENDITIONS['picture'],
                 url_for_media=url_for_media
             )
         data = [{
             'headline': headline,
             'slugline': 'rebuild',
             'renditions': renditions,
             'type': 'picture'
         }]
         image_id = get_resource_service('ingest').post(data)
     with open(verification_result_path, 'r') as f:
         self.expected_verification_results.append(json.load(f))
     with open(verification_stats_path, 'r') as f:
         self.expected_verification_stats.append(json.load(f))
     return image_id
    def create(self, docs, **kwargs):
        ids = []
        for doc in docs:
            item = doc.pop('item')
            orig = item['renditions']['original']
            orig_file = get_file(orig, item)
            no_custom_crops = doc.get('no_custom_crops', False)
            rendition_spec = get_renditions_spec(
                no_custom_crops=no_custom_crops)
            inserted = []
            mimetype = item.get('mimetype', orig.get('mimetype', '/'))
            media_type, content_type = mimetype.split('/')
            renditions = generate_renditions(orig_file, orig['media'],
                                             inserted, media_type, mimetype,
                                             rendition_spec,
                                             app.media.url_for_media)

            doc['renditions'] = renditions
            ids.append(item['_id'])

            updates = {'renditions': item['renditions']}
            try:
                get_resource_service('archive').update(item['_id'], updates,
                                                       item)
            except Exception as ex:
                logger.warning(
                    'failed to update the renditions for original item in archive'
                )
        return ids
Example #14
0
    def store_file(self, doc, content, filename, content_type):
        res = process_file_from_stream(content, filename=filename, content_type=content_type)
        file_name, content_type, metadata = res

        cropping_data = self.get_cropping_data(doc)
        _, out = crop_image(content, filename, cropping_data)
        metadata['length'] = json.dumps(len(out.getvalue()))

        try:
            logger.debug('Going to save media file with %s ' % file_name)
            out.seek(0)
            id = app.media.put(out, filename=file_name, content_type=content_type, metadata=metadata)
            doc['media'] = id
            doc['mime_type'] = content_type
            doc['filemeta'] = decode_metadata(metadata)
            inserted = [doc['media']]
            file_type = content_type.split('/')[0]

            rendition_spec = config.RENDITIONS['avatar']
            renditions = generate_renditions(out, doc['media'], inserted, file_type,
                                             content_type, rendition_spec, url_for_media)
            doc['renditions'] = renditions
        except Exception as io:
            logger.exception(io)
            for file_id in inserted:
                delete_file_on_error(doc, file_id)
            raise SuperdeskError(message='Generating renditions failed')
    def setUp(self):
        super().setUp()
        dirname = os.path.dirname(os.path.realpath(__file__))
        image_path = os.path.normpath(
            os.path.join(dirname, "fixtures", self.filename))
        content_type = mimetypes.guess_type(image_path)[0]
        guid = utils.generate_guid(type=GUID_TAG)
        self.item = {
            "guid": guid,
            "version": 1,
            "_id": guid,
            ITEM_TYPE: CONTENT_TYPE.PICTURE,
            "mimetype": content_type,
            "versioncreated": datetime.now(),
        }

        with open(image_path, "rb") as f:
            _, content_type, file_metadata = process_file_from_stream(
                f, content_type=content_type)
            f.seek(0)
            file_id = app.media.put(f,
                                    filename=self.filename,
                                    content_type=content_type,
                                    metadata=file_metadata)
            filemeta.set_filemeta(self.item, file_metadata)
            f.seek(0)
            rendition_spec = get_renditions_spec()
            renditions = generate_renditions(f, file_id, [file_id], "image",
                                             content_type, rendition_spec,
                                             url_for_media)
            self.item["renditions"] = renditions
        archive = get_resource_service("archive")
        archive.post([self.item])
Example #16
0
    def parse_item(self, image_path):
        filename = os.path.basename(image_path)
        content_type = mimetypes.guess_type(image_path)[0]
        guid = utils.generate_guid(type=GUID_TAG)
        item = {'guid': guid,
                'uri': guid,
                config.VERSION: 1,
                ITEM_TYPE: CONTENT_TYPE.PICTURE,
                'mimetype': content_type,
                'versioncreated': utcnow(),
                }
        with open(image_path, 'rb') as f:
            _, content_type, file_metadata = process_file_from_stream(f, content_type=content_type)
            f.seek(0)
            file_id = app.media.put(f, filename=filename, content_type=content_type, metadata=file_metadata)
            filemeta.set_filemeta(item, file_metadata)
            f.seek(0)

            metadata = get_meta_iptc(f)
            f.seek(0)
            self.parse_meta(item, metadata)

            rendition_spec = get_renditions_spec(no_custom_crops=True)
            renditions = generate_renditions(f, file_id, [file_id], 'image',
                                             content_type, rendition_spec, url_for_media)
            item['renditions'] = renditions
        return item
    def test_generate_renditions_custom_crop(self):
        inserted = []
        renditions = get_renditions_spec()
        with open(IMG_PATH, "rb") as original:
            generated = generate_renditions(
                original, "id", inserted, "image", "image/jpeg", renditions, self.app.media.url_for_media
            )

        # thumbnail should keep 4:3 ration
        self.assertIn("thumbnail", generated)
        self.assertEqual(160, generated["thumbnail"]["width"])
        self.assertEqual(120, generated["thumbnail"]["height"])

        # landscape should be cropped to 200x100
        self.assertIn("landscape", generated)
        landscape = generated["landscape"]
        self.assertEqual(200, landscape["width"])
        self.assertEqual(100, landscape["height"])
        self.assertEqual(0, landscape["CropLeft"])
        self.assertEqual(400, landscape["CropRight"])
        self.assertEqual(50, landscape["CropTop"])
        self.assertEqual(250, landscape["CropBottom"])

        # portrait should be cropped to 150x200
        self.assertIn("portrait", generated)
        portrait = generated["portrait"]
        self.assertEqual(150, portrait["width"])
        self.assertEqual(200, portrait["height"])
        self.assertEqual(0, portrait["CropTop"])
        self.assertEqual(300, portrait["CropBottom"])
        self.assertEqual(87, portrait["CropLeft"])
        self.assertEqual(312, portrait["CropRight"])
Example #18
0
    def find_one_raw(self, resource, _id):
        # XXX: preview is used here instead of paid download
        #      see SDNTB-15
        data = {}
        url = self._app.config['SCANPIX_SEARCH_URL'] + '/search'
        data['refPtrs'] = [_id]
        r = self._request(url, data)
        doc = r.json()['data'][0]
        self._parse_doc(doc)

        url = doc['renditions']['baseImage']['href']
        # if MIME type can't be guessed, we default to jpeg
        mime_type = mimetypes.guess_type(url)[0] or 'image/jpeg'

        r = self._request(url, data)
        out = BytesIO(r.content)
        file_name, content_type, metadata = process_file_from_stream(
            out, mime_type)

        logger.debug('Going to save media file with %s ' % file_name)
        out.seek(0)
        try:
            file_id = self._app.media.put(out,
                                          filename=file_name,
                                          content_type=content_type,
                                          metadata=None)
        except Exception as e:
            logger.exception(e)
            raise SuperdeskApiError.internalError('Media saving failed')
        else:
            try:
                inserted = [file_id]
                doc['mimetype'] = content_type
                doc['filemeta'] = decode_metadata(metadata)
                # set the version created to now to bring it to the top of the desk, images can be quite old
                doc['versioncreated'] = utcnow()
                file_type = content_type.split('/')[0]
                rendition_spec = get_renditions_spec()
                renditions = generate_renditions(out,
                                                 file_id,
                                                 inserted,
                                                 file_type,
                                                 content_type,
                                                 rendition_spec,
                                                 url_for_media,
                                                 insert_metadata=False)
                doc['renditions'] = renditions
            except (IndexError, KeyError, json.JSONDecodeError) as e:
                logger.exception("Internal error: {}".format(e))
                delete_file_on_error(doc, file_id)

                raise SuperdeskApiError.internalError(
                    'Generating renditions failed')
        return doc
    def on_create(self, docs):
        """Create corresponding item on file upload."""

        for doc in docs:
            if 'media' not in doc or doc['media'] is None:
                abort(400, description="No media found")
            # check content type of video by python-magic
            content_type = magic.from_buffer(doc['media'].read(1024),
                                             mime=True)
            doc['media'].seek(0)
            file_type = content_type.split('/')[0]
            if file_type == 'video' and app.config.get("VIDEO_SERVER_ENABLE"):
                if not self.videoEditor.check_video_server():
                    raise SuperdeskApiError(
                        message="Cannot connect to videoserver",
                        status_code=500)
                # upload media to video server
                res, renditions, metadata = self.upload_file_to_video_server(
                    doc)
                # get thumbnails for timeline bar
                self.videoEditor.get_timeline_thumbnails(doc.get('media'), 40)
            else:
                file, content_type, metadata = self.get_file_from_document(doc)
                inserted = [doc['media']]
                # if no_custom_crops is set to False the custom crops are generated automatically on media upload
                # see (SDESK-4742)
                rendition_spec = get_renditions_spec(
                    no_custom_crops=app.config.get("NO_CUSTOM_CROPS"))
                with timer('archive:renditions'):
                    renditions = generate_renditions(file, doc['media'],
                                                     inserted, file_type,
                                                     content_type,
                                                     rendition_spec,
                                                     url_for_media)
            try:
                self._set_metadata(doc)
                doc[ITEM_TYPE] = self.type_av.get(file_type)
                doc[ITEM_STATE] = CONTENT_STATE.PROGRESS
                doc['renditions'] = renditions
                doc['mimetype'] = content_type
                set_filemeta(doc, metadata)
                add_activity('upload',
                             'uploaded media {{ name }}',
                             'archive',
                             item=doc,
                             name=doc.get('headline', doc.get('mimetype')),
                             renditions=doc.get('renditions'))
            except Exception as io:
                logger.exception(io)
                for file_id in inserted:
                    delete_file_on_error(doc, file_id)
                if res:
                    self.videoEditor.delete(res.get('_id'))
                abort(500)
Example #20
0
    def on_create(self, docs):
        """Create corresponding item on file upload."""

        for doc in docs:
            if "media" not in doc or doc["media"] is None:
                abort(400, description="No media found")
            # check content type of video by python-magic
            content_type = app.media._get_mimetype(doc["media"])
            doc["media"].seek(0)
            file_type = content_type.split("/")[0]
            if file_type == "video" and app.config.get("VIDEO_SERVER_ENABLED"):
                # upload media to video server
                res, renditions, metadata = self.upload_file_to_video_server(
                    doc)
                # get thumbnails for timeline bar
                self.video_editor.create_timeline_thumbnails(
                    doc.get("media"), 60)
            else:
                file, content_type, metadata = self.get_file_from_document(doc)
                inserted = [doc["media"]]
                # if no_custom_crops is set to False the custom crops are generated automatically on media upload
                # see (SDESK-4742)
                rendition_spec = get_renditions_spec(
                    no_custom_crops=app.config.get("NO_CUSTOM_CROPS"))
                with timer("archive:renditions"):
                    renditions = generate_renditions(file, doc["media"],
                                                     inserted, file_type,
                                                     content_type,
                                                     rendition_spec,
                                                     url_for_media)
            try:
                self._set_metadata(doc)
                doc[ITEM_TYPE] = self.type_av.get(file_type)
                doc[ITEM_STATE] = CONTENT_STATE.PROGRESS
                doc["renditions"] = renditions
                doc["mimetype"] = content_type
                set_filemeta(doc, metadata)
                add_activity(
                    "upload",
                    "uploaded media {{ name }}",
                    "archive",
                    item=doc,
                    name=doc.get("headline", doc.get("mimetype")),
                    renditions=doc.get("renditions"),
                )
            except Exception as io:
                logger.exception(io)
                for file_id in inserted:
                    delete_file_on_error(doc, file_id)
                if res:
                    self.video_editor.delete(res.get("_id"))
                abort(500)
Example #21
0
    def parse_item(self, image_path):
        filename = os.path.basename(image_path)
        content_type = mimetypes.guess_type(image_path)[0]
        guid = utils.generate_guid(type=GUID_TAG)
        item = {
            'guid': guid,
            config.VERSION: 1,
            config.ID_FIELD: guid,
            ITEM_TYPE: CONTENT_TYPE.PICTURE,
            'mimetype': content_type,
            'versioncreated': datetime.now()
        }
        with open(image_path, 'rb') as f:
            _, content_type, file_metadata = process_file_from_stream(
                f, content_type=content_type)
            f.seek(0)
            file_id = app.media.put(f,
                                    filename=filename,
                                    content_type=content_type,
                                    metadata=file_metadata)
            filemeta.set_filemeta(item, file_metadata)
            f.seek(0)
            metadata = get_meta_iptc(f)
            f.seek(0)
            rendition_spec = get_renditions_spec(no_custom_crops=True)
            renditions = generate_renditions(f, file_id, [file_id], 'image',
                                             content_type, rendition_spec,
                                             url_for_media)
            item['renditions'] = renditions

        try:
            date_created, time_created = metadata[TAG.DATE_CREATED], metadata[
                TAG.TIME_CREATED]
        except KeyError:
            pass
        else:
            # we format proper ISO 8601 date so we can parse it with dateutil
            datetime_created = '{}-{}-{}T{}:{}:{}{}{}:{}'.format(
                date_created[0:4], date_created[4:6], date_created[6:8],
                time_created[0:2], time_created[2:4], time_created[4:6],
                time_created[6], time_created[7:9], time_created[9:])
            item['firstcreated'] = dateutil.parser.parse(datetime_created)

        # now we map IPTC metadata to superdesk metadata
        for source_key, dest_key in IPTC_MAPPING.items():
            try:
                item[dest_key] = metadata[source_key]
            except KeyError:
                continue
        return item
 def create(self, docs, **kwargs):
     ids = []
     for doc in docs:
         item = doc.pop('item')
         orig = item['renditions']['original']
         orig_file = get_file(orig, item)
         rendition_spec = get_renditions_spec()
         inserted = []
         media_type, content_type = item['mimetype'].split('/')
         renditions = generate_renditions(orig_file, orig['media'], inserted, media_type,
                                          item['mimetype'], rendition_spec, app.media.url_for_media)
         doc['renditions'] = renditions
         ids.append(item['_id'])
     return ids
    def test_generate_renditions_base_image(self):
        inserted = []
        renditions = get_renditions_spec()
        with open(BIG_IMG_PATH, 'rb') as original:
            generated = generate_renditions(original, 'id', inserted, 'image', 'image/jpeg', renditions,
                                            self.app.media.url_for_media)

        self.assertIn('landscape', generated)
        landscape = generated['landscape']
        self.assertEqual(200, landscape['width'])
        self.assertEqual(100, landscape['height'])
        self.assertEqual(0, landscape['CropLeft'])
        self.assertEqual(1200, landscape['CropRight'])
        self.assertEqual(500, landscape['CropTop'])
        self.assertEqual(1100, landscape['CropBottom'])
Example #24
0
 def create(self, docs, **kwargs):
     ids = []
     for doc in docs:
         item = doc.pop('item')
         orig = item['renditions']['original']
         orig_file = get_file(orig, item)
         rendition_spec = get_renditions_spec()
         inserted = []
         mimetype = item.get('mimetype', orig.get('mimetype', '/'))
         media_type, content_type = mimetype.split('/')
         renditions = generate_renditions(orig_file, orig['media'], inserted, media_type,
                                          mimetype, rendition_spec, app.media.url_for_media)
         doc['renditions'] = renditions
         ids.append(item['_id'])
     return ids
    def parse_item(self, image_path):
        filename = os.path.basename(image_path)
        content_type = mimetypes.guess_type(image_path)[0]
        guid = utils.generate_guid(type=GUID_TAG)
        item = {'guid': guid,
                config.VERSION: 1,
                config.ID_FIELD: guid,
                ITEM_TYPE: CONTENT_TYPE.PICTURE,
                'mimetype': content_type,
                'versioncreated': datetime.now()
                }
        with open(image_path, 'rb') as f:
            _, content_type, file_metadata = process_file_from_stream(f, content_type=content_type)
            f.seek(0)
            file_id = app.media.put(f, filename=filename, content_type=content_type, metadata=file_metadata)
            filemeta.set_filemeta(item, file_metadata)
            f.seek(0)
            metadata = get_meta_iptc(f)
            f.seek(0)
            rendition_spec = get_renditions_spec(no_custom_crops=True)
            renditions = generate_renditions(f, file_id, [file_id], 'image',
                                             content_type, rendition_spec, url_for_media)
            item['renditions'] = renditions

        try:
            date_created, time_created = metadata[TAG.DATE_CREATED], metadata[TAG.TIME_CREATED]
        except KeyError:
            pass
        else:
            # we format proper ISO 8601 date so we can parse it with dateutil
            datetime_created = '{}-{}-{}T{}:{}:{}{}{}:{}'.format(date_created[0:4],
                                                                 date_created[4:6],
                                                                 date_created[6:8],
                                                                 time_created[0:2],
                                                                 time_created[2:4],
                                                                 time_created[4:6],
                                                                 time_created[6],
                                                                 time_created[7:9],
                                                                 time_created[9:])
            item['firstcreated'] = dateutil.parser.parse(datetime_created)

        # now we map IPTC metadata to superdesk metadata
        for source_key, dest_key in IPTC_MAPPING.items():
            try:
                item[dest_key] = metadata[source_key]
            except KeyError:
                continue
        return item
    def on_create(self, docs):
        """ Create corresponding item on file upload """

        for doc in docs:
            if 'media' not in doc or doc['media'] is None:
                abort(400, description="No media found")

            file, content_type, metadata = self.get_file_from_document(doc)
            inserted = [doc['media']]
            file_type = content_type.split('/')[0]

            try:
                update_dates_for(doc)
                generate_unique_id_and_name(doc)
                doc['guid'] = generate_guid(type=GUID_TAG)
                doc.setdefault('_id', doc['guid'])

                doc['type'] = self.type_av.get(file_type)
                doc[config.VERSION] = 1
                doc['versioncreated'] = utcnow()
                set_item_expiry({}, doc)

                rendition_spec = config.RENDITIONS['picture']
                renditions = generate_renditions(file, doc['media'], inserted,
                                                 file_type, content_type,
                                                 rendition_spec, url_for_media)
                doc['renditions'] = renditions
                doc['mimetype'] = content_type
                doc['filemeta'] = metadata

                if not doc.get('_import', None):
                    set_original_creator(doc)

                doc.setdefault(config.CONTENT_STATE, 'draft')

                add_activity('upload',
                             'uploaded media {{ name }}',
                             item=doc,
                             name=doc.get('headline', doc.get('mimetype')),
                             renditions=doc.get('renditions'))

            except Exception as io:
                logger.exception(io)
                for file_id in inserted:
                    delete_file_on_error(doc, file_id)
                abort(500)

        on_create_media_archive()
    def test_generate_renditions_base_image(self):
        inserted = []
        renditions = get_renditions_spec()
        with open(BIG_IMG_PATH, "rb") as original:
            generated = generate_renditions(
                original, "id", inserted, "image", "image/jpeg", renditions, self.app.media.url_for_media
            )

        self.assertIn("landscape", generated)
        landscape = generated["landscape"]
        self.assertEqual(200, landscape["width"])
        self.assertEqual(100, landscape["height"])
        self.assertEqual(0, landscape["CropLeft"])
        self.assertEqual(1200, landscape["CropRight"])
        self.assertEqual(500, landscape["CropTop"])
        self.assertEqual(1100, landscape["CropBottom"])
Example #28
0
    def find_one_raw(self, resource, _id):
        url = self._app.config['AAP_MM_SEARCH_URL'] + '/Assets/{}'.format(_id)
        r = self._http.request('GET', url, headers=self._headers)
        doc = json.loads(r.data.decode('UTF-8'))
        self._parse_doc(doc)
        if 'fetch_endpoint' in doc:
            del doc['fetch_endpoint']

        # Only if we have credentials can we download the original if the account has that privilege
        if 'AAP_MM_USER' in self._app.config and 'AAP_MM_PASSWORD' in self._app.config \
                and self._app.config['AAP_MM_USER'] is not None:
            url = self._app.config[
                'AAP_MM_SEARCH_URL'] + '/Assets/{}/Original/download'.format(
                    _id)
        else:
            url = doc['renditions']['original']['href']
        r = self._http.request('GET', url, headers=self._headers)

        out = BytesIO(r.data)
        file_name, content_type, metadata = process_file_from_stream(
            out, 'image/jpeg')

        try:
            logger.debug('Going to save media file with %s ' % file_name)
            out.seek(0)
            file_id = self._app.media.put(out,
                                          filename=file_name,
                                          content_type=content_type,
                                          metadata=metadata)
            doc['mimetype'] = content_type
            doc['filemeta'] = decode_metadata(metadata)
            # set the version created to now to bring it to the top of the desk, images can be quite old
            doc['versioncreated'] = utcnow()
            inserted = [file_id]
            file_type = content_type.split('/')[0]
            rendition_spec = self._app.config['RENDITIONS']['picture']

            renditions = generate_renditions(out, file_id, inserted, file_type,
                                             content_type, rendition_spec,
                                             self.url_for_media)
            doc['renditions'] = renditions
        except Exception as io:
            logger.exception(io)
            for file_id in inserted:
                delete_file_on_error(doc, file_id)

        return doc
Example #29
0
    def create(self, docs):
        """Apply transformation requested in "edit"

        an item with updated rendition will be returned.
        All created files are temporary, meaning they will be deleted after a delay or a cleaning.
        """
        try:
            item = request.json['item']
        except KeyError:
            try:
                item_id = request.json['item_id']
            except KeyError:
                raise errors.SuperdeskApiError.badRequestError(
                    'either item or item_id must be specified')
            item = next(get_resource_service('archive').find({'_id': item_id}))
        edit = request.json['edit']
        rendition = item['renditions']['original']
        media_id = rendition['media']
        media = current_app.media.get(media_id)
        out = im = Image.open(media)
        for operation, param in edit.items():
            try:
                out = self.transform(out, operation, param)
            except ValueError as e:
                raise errors.SuperdeskApiError.badRequestError(
                    'invalid edit instructions: {msg}'.format(msg=e))
        buf = BytesIO()
        out.save(buf, format=im.format)
        buf.seek(0)
        content_type = rendition['mimetype']
        ext = os.path.splitext(rendition['href'])[1]
        filename = str(uuid.uuid4()) + ext
        media_id = current_app.media.put(buf,
                                         filename=filename,
                                         content_type=content_type,
                                         folder='temp')
        buf.seek(0)
        renditions = generate_renditions(buf,
                                         media_id, [],
                                         'image',
                                         content_type,
                                         get_renditions_spec(),
                                         current_app.media.url_for_media,
                                         temporary=True)
        item['renditions'] = renditions
        docs[:] = [item]
        return [item['_id']]
Example #30
0
    def on_create(self, docs):
        """ Create corresponding item on file upload """

        for doc in docs:
            if 'media' not in doc or doc['media'] is None:
                abort(400, description="No media found")

            file, content_type, metadata = self.get_file_from_document(doc)
            inserted = [doc['media']]
            file_type = content_type.split('/')[0]

            try:
                update_dates_for(doc)
                generate_unique_id_and_name(doc)
                doc['guid'] = generate_guid(type=GUID_TAG)
                doc.setdefault('_id', doc['guid'])

                doc['type'] = self.type_av.get(file_type)
                doc[config.VERSION] = 1
                doc['versioncreated'] = utcnow()
                set_item_expiry({}, doc)

                rendition_spec = config.RENDITIONS['picture']
                renditions = generate_renditions(file, doc['media'], inserted, file_type,
                                                 content_type, rendition_spec, url_for_media)
                doc['renditions'] = renditions
                doc['mimetype'] = content_type
                doc['filemeta'] = metadata

                if not doc.get('_import', None):
                    set_original_creator(doc)

                doc.setdefault(config.CONTENT_STATE, 'draft')

                if not doc.get('ingest_provider'):
                    doc['source'] = DEFAULT_SOURCE_VALUE_FOR_MANUAL_ARTICLES

                add_activity('upload', 'uploaded media {{ name }}',
                             'archive', item=doc,
                             name=doc.get('headline', doc.get('mimetype')),
                             renditions=doc.get('renditions'))

            except Exception as io:
                logger.exception(io)
                for file_id in inserted:
                    delete_file_on_error(doc, file_id)
                abort(500)
Example #31
0
def update_renditions(item, href):
    inserted = []
    try:
        content, filename, content_type = download_file_from_url(href)
        file_type, ext = content_type.split('/')
        metadata = process_file(content, file_type)
        file_guid = app.media.put(content, filename, content_type, metadata)
        inserted.append(file_guid)

        rendition_spec = app.config.get('RENDITIONS', {}).get('picture', {})
        renditions = generate_renditions(content, file_guid, inserted, file_type,
                                         content_type, rendition_spec, url_for_media)
        item['renditions'] = renditions
        item['mimetype'] = content_type
        item['filemeta'] = metadata
    except Exception:
        for file_id in inserted:
            app.media.delete(file_id)
        raise
Example #32
0
    def find_one_raw(self, resource, _id):
        if self._headers is None:
            self.__set_auth_cookie(self._app)

        url = self._app.config['AAP_MM_SEARCH_URL'] + '/Assets/{}'.format(_id)
        r = self._http.request('GET', url, headers=self._headers)
        doc = json.loads(r.data.decode('UTF-8'))
        self._parse_doc(doc)
        if 'fetch_endpoint' in doc:
            del doc['fetch_endpoint']

        # Only if we have credentials can we download the original if the account has that privilege
        if 'AAP_MM_USER' in self._app.config and 'AAP_MM_PASSWORD' in self._app.config \
                and self._app.config['AAP_MM_USER'] is not None:
            url = self._app.config['AAP_MM_SEARCH_URL'] + '/Assets/{}/Original/download'.format(_id)
        else:
            url = doc['renditions']['original']['href']
        r = self._http.request('GET', url, headers=self._headers)

        out = BytesIO(r.data)
        file_name, content_type, metadata = process_file_from_stream(out, 'image/jpeg')

        try:
            logger.debug('Going to save media file with %s ' % file_name)
            out.seek(0)
            file_id = self._app.media.put(out, filename=file_name, content_type=content_type, metadata=metadata)
            doc['mimetype'] = content_type
            doc['filemeta'] = decode_metadata(metadata)
            # set the version created to now to bring it to the top of the desk, images can be quite old
            doc['versioncreated'] = utcnow()
            inserted = [file_id]
            file_type = content_type.split('/')[0]
            rendition_spec = self._app.config['RENDITIONS']['picture']

            renditions = generate_renditions(out, file_id, inserted, file_type,
                                             content_type, rendition_spec, self.url_for_media)
            doc['renditions'] = renditions
        except Exception as io:
            logger.exception(io)
            for file_id in inserted:
                delete_file_on_error(doc, file_id)

        return doc
Example #33
0
    def on_create(self, docs):
        """ Create corresponding item on file upload """

        for doc in docs:
            if 'media' not in doc or doc['media'] is None:
                abort(400, description="No media found")

            file, content_type, metadata = self.get_file_from_document(doc)
            inserted = [doc['media']]
            file_type = content_type.split('/')[0]

            self._set_metadata(doc)

            try:
                doc[ITEM_TYPE] = self.type_av.get(file_type)
                # renditions required by superdesk
                rendition_spec = config.RENDITIONS['picture']
                # load custom crop sizes
                custom_crops = get_resource_service('vocabularies').find_one(
                    req=None, _id='crop_sizes')
                if custom_crops:
                    for crop in custom_crops.get('items'):
                        # complete list of wanted renditions
                        rendition_spec[crop['name']] = crop
                renditions = generate_renditions(file, doc['media'], inserted,
                                                 file_type, content_type,
                                                 rendition_spec, url_for_media)
                doc['renditions'] = renditions
                doc['mimetype'] = content_type
                doc['filemeta'] = metadata

                add_activity('upload',
                             'uploaded media {{ name }}',
                             'archive',
                             item=doc,
                             name=doc.get('headline', doc.get('mimetype')),
                             renditions=doc.get('renditions'))
            except Exception as io:
                logger.exception(io)
                for file_id in inserted:
                    delete_file_on_error(doc, file_id)
                abort(500)
Example #34
0
def update_renditions(item, href, old_item):
    """Update renditions for an item.

    If the old_item has renditions uploaded in to media then the old rendition details are
    assigned to the item, this avoids repeatedly downloading the same image and leaving the media entries orphaned.
    If there is no old_item the original is downloaded and renditions are
    generated.
    :param item: parsed item from source
    :param href: reference to original
    :param old_item: the item that we have already ingested, if it exists
    :return: item with renditions
    """
    inserted = []
    try:
        # If there is an existing set of renditions we keep those
        if old_item:
            media = old_item.get('renditions', {}).get('original',
                                                       {}).get('media', {})
            if media:
                item['renditions'] = old_item['renditions']
                item['mimetype'] = old_item.get('mimetype')
                item['filemeta'] = old_item.get('filemeta')
                item['filemeta_json'] = old_item.get('filemeta_json')
                return

        content, filename, content_type = download_file_from_url(href)
        file_type, ext = content_type.split('/')
        metadata = process_file(content, file_type)
        file_guid = app.media.put(content, filename, content_type, metadata)
        inserted.append(file_guid)
        rendition_spec = get_renditions_spec()
        renditions = generate_renditions(content, file_guid, inserted,
                                         file_type, content_type,
                                         rendition_spec, url_for_media)
        item['renditions'] = renditions
        item['mimetype'] = content_type
        set_filemeta(item, metadata)
    except Exception as e:
        logger.exception(e)
        for file_id in inserted:
            app.media.delete(file_id)
        raise
Example #35
0
def update_renditions(item, href):
    inserted = []
    try:
        content, filename, content_type = download_file_from_url(href)
        file_type, ext = content_type.split('/')
        metadata = process_file(content, file_type)
        file_guid = app.media.put(content, filename, content_type, metadata)
        inserted.append(file_guid)

        rendition_spec = app.config.get('RENDITIONS', {}).get('picture', {})
        renditions = generate_renditions(content, file_guid, inserted,
                                         file_type, content_type,
                                         rendition_spec, url_for_media)
        item['renditions'] = renditions
        item['mimetype'] = content_type
        item['filemeta'] = metadata
    except Exception:
        for file_id in inserted:
            app.media.delete(file_id)
        raise
Example #36
0
    def on_create(self, docs):
        """Create corresponding item on file upload."""

        for doc in docs:
            if 'media' not in doc or doc['media'] is None:
                abort(400, description="No media found")

            file, content_type, metadata = self.get_file_from_document(doc)
            inserted = [doc['media']]
            file_type = content_type.split('/')[0]

            self._set_metadata(doc)

            try:
                doc[ITEM_TYPE] = self.type_av.get(file_type)
                doc[ITEM_STATE] = CONTENT_STATE.PROGRESS
                # if no_custom_crops is set to False the custom crops are generated automatically on media upload
                # see (SDESK-4742)
                rendition_spec = get_renditions_spec(
                    no_custom_crops=app.config.get("NO_CUSTOM_CROPS"))
                with timer('archive:renditions'):
                    renditions = generate_renditions(file, doc['media'],
                                                     inserted, file_type,
                                                     content_type,
                                                     rendition_spec,
                                                     url_for_media)
                doc['renditions'] = renditions
                doc['mimetype'] = content_type
                set_filemeta(doc, metadata)

                add_activity('upload',
                             'uploaded media {{ name }}',
                             'archive',
                             item=doc,
                             name=doc.get('headline', doc.get('mimetype')),
                             renditions=doc.get('renditions'))
            except Exception as io:
                logger.exception(io)
                for file_id in inserted:
                    delete_file_on_error(doc, file_id)
                abort(500)
Example #37
0
    def create(self, docs, **kwargs):
        ids = []
        for doc in docs:
            item = doc.pop("item")
            orig = item["renditions"]["original"]
            orig_file = get_file(orig, item)
            no_custom_crops = doc.get("no_custom_crops", False)
            rendition_spec = get_renditions_spec(
                no_custom_crops=no_custom_crops)
            inserted = []
            mimetype = item.get("mimetype", orig.get("mimetype", "/"))
            media_type, content_type = mimetype.split("/")
            renditions = generate_renditions(orig_file, orig["media"],
                                             inserted, media_type, mimetype,
                                             rendition_spec,
                                             app.media.url_for_media)

            doc["renditions"] = renditions
            ids.append(item["_id"])

        return ids
def update_renditions(item, href, old_item):
    """
    If the old_item has renditions uploaded in to media then the old rendition details are
    assigned to the item, this avoids repeatedly downloading the same image and leaving the media entries orphaned.
    If there is no old_item the original is downloaded and renditions are
    generated.
    :param item: parsed item from source
    :param href: reference to original
    :param old_item: the item that we have already injested, if it exists
    :return: item with renditions
    """
    inserted = []
    try:
        # If there is an existing set of renditions we keep those
        if old_item:
            media = old_item.get('renditions', {}).get('original', {}).get('media', {})
            if media:
                item['renditions'] = old_item['renditions']
                item['mimetype'] = old_item.get('mimetype')
                item['filemeta'] = old_item.get('filemeta')
                logger.info("Reuters image not updated for GUID:{}".format(item[GUID_FIELD]))
                return

        content, filename, content_type = download_file_from_url(href)
        file_type, ext = content_type.split('/')

        metadata = process_file(content, file_type)
        file_guid = app.media.put(content, filename, content_type, metadata)
        inserted.append(file_guid)

        rendition_spec = app.config.get('RENDITIONS', {}).get('picture', {})
        renditions = generate_renditions(content, file_guid, inserted, file_type,
                                         content_type, rendition_spec, url_for_media)
        item['renditions'] = renditions
        item['mimetype'] = content_type
        item['filemeta'] = metadata
    except Exception:
        for file_id in inserted:
            app.media.delete(file_id)
        raise
    def create(self, docs):
        """Apply transformation requested in 'edit'"""
        ids = []
        archive = get_resource_service('archive')

        for idx, doc in enumerate(docs):
            # first we get item and requested edit operations
            try:
                item = doc.pop('item')
            except KeyError:
                try:
                    item_id = doc.pop('item_id')
                except KeyError:
                    raise errors.SuperdeskApiError.badRequestError(
                        'either item or item_id must be specified')
            else:
                item_id = item[config.ID_FIELD]

            item = next(archive.find({'_id': item_id}))
            edit = doc.pop('edit')

            # now we retrieve and load current original media
            rendition = item['renditions']['original']
            media_id = rendition['media']
            media = current_app.media.get(media_id)
            out = im = Image.open(media)

            # we apply all requested operations on original media
            for operation, param in edit.items():
                try:
                    out = self.transform(out, operation, param)
                except ValueError:
                    # if the operation can't be applied just ignore it
                    logger.warning(
                        'failed to apply operation: {operation} {param} for media {id}'
                        .format(operation=operation, param=param, id=media_id))
            buf = BytesIO()
            out.save(buf, format=im.format)

            # we set metadata
            buf.seek(0)
            content_type = rendition['mimetype']
            ext = os.path.splitext(rendition['href'])[1]
            filename = str(uuid.uuid4()) + ext

            # and save transformed media in database
            media_id = current_app.media.put(buf,
                                             filename=filename,
                                             content_type=content_type)

            # now we recreate other renditions based on transformed original media
            buf.seek(0)
            renditions = generate_renditions(buf, media_id, [],
                                             'image', content_type,
                                             get_renditions_spec(),
                                             current_app.media.url_for_media)

            # we update item in db, and the item we'll return to client
            # we keep old renditions in GridFS for history references
            updates = {'renditions': renditions}
            ids.append(item_id)
            archive.update(item_id, updates, item)
            item.update(updates)

            docs[idx] = item

        return [ids]
Example #40
0
    def create(self, docs):
        """Apply transformation requested in 'edit'"""
        ids = []
        archive = get_resource_service('archive')

        for idx, doc in enumerate(docs):
            # first we get item and requested edit operations
            try:
                item = doc.pop('item')
            except KeyError:
                try:
                    item_id = doc.pop('item_id')
                except KeyError:
                    raise errors.SuperdeskApiError.badRequestError('either item or item_id must be specified')
            else:
                item_id = item[config.ID_FIELD]

            item = next(archive.find({'_id': item_id}))
            edit = doc.pop('edit')

            # new we retrieve and loag current original media
            rendition = item['renditions']['original']
            media_id = rendition['media']
            media = current_app.media.get(media_id)
            out = im = Image.open(media)

            # we apply all requested operations on original media
            for operation, param in edit.items():
                try:
                    out = self.transform(out, operation, param)
                except ValueError as e:
                    raise errors.SuperdeskApiError.badRequestError('invalid edit instructions: {msg}'.format(msg=e))
            buf = BytesIO()
            out.save(buf, format=im.format)

            # we set metadata
            buf.seek(0)
            content_type = rendition['mimetype']
            ext = os.path.splitext(rendition['href'])[1]
            filename = str(uuid.uuid4()) + ext

            # and save transformed media in database
            media_id = current_app.media.put(buf, filename=filename, content_type=content_type, folder='temp')

            # now we recreate other renditions based on transformed original media
            buf.seek(0)
            # we keep old renditions to later delete old files
            renditions = generate_renditions(buf,
                                             media_id,
                                             [],
                                             'image',
                                             content_type,
                                             get_renditions_spec(),
                                             current_app.media.url_for_media,
                                             temporary=True)

            # we update item in db, and the item we'll return to client
            updates = {'renditions': renditions}
            ids.append(item_id)
            archive.update(item_id, updates, item)
            # we keep old renditions to later delete old files
            item.update(updates)

            docs[idx] = item

        return [ids]
Example #41
0
    def find_one_raw(self, resource, _id):
        if self._headers is None:
            self.__set_auth_cookie(self._app)

        url = self._app.config["AAP_MM_SEARCH_URL"] + "/Assets/{}".format(_id)
        r = self._http.request("GET", url, headers=self._headers)
        doc = json.loads(r.data.decode("UTF-8"))
        self._parse_doc(doc)
        if "fetch_endpoint" in doc:
            del doc["fetch_endpoint"]

        # Only if we have credentials can we download the original if the account has that privilege
        if self._username is not None and self._password is not None:
            resolutions = self._get_resolutions(_id)
            if doc["type"] == "picture":
                if any(i["Name"] == "Original" for i in resolutions["Image"]):
                    url = self._app.config["AAP_MM_SEARCH_URL"] + "/Assets/{}/Original/download".format(_id)
                    mime_type = "image/jpeg"
                    source_ref = {"href": url, "mimetype": mime_type}
                else:
                    raise FileNotFoundError
            elif doc["type"] == "video":
                if any(v["Name"] == "Ipod" for v in resolutions["Video"]):
                    url = self._app.config["AAP_MM_SEARCH_URL"] + "/Assets/{}/Ipod/download".format(_id)
                    mime_type = doc.get("renditions").get("original").get("mimetype")
                else:
                    raise FileNotFoundError
                if any(v["Name"] == "Video" for v in resolutions["Video"]):
                    source_ref = {
                        "href": self._app.config["AAP_MM_SEARCH_URL"] + "/Assets/{}/Video/download".format(_id),
                        "mimetype": "video/quicktime",
                    }
                else:
                    raise FileNotFoundError
            else:
                raise NotImplementedError
        else:
            if doc["type"] == "video":
                mime_type = doc.get("renditions").get("original").get("mimetype")
            else:
                mime_type = "image/jpeg"
            url = doc["renditions"]["original"]["href"]
            source_ref = {"href": url, "mimetype": mime_type}

        r = self._http.request("GET", url, headers=self._headers)
        out = BytesIO(r.data)
        file_name, content_type, metadata = process_file_from_stream(out, mime_type)

        try:
            logger.debug("Going to save media file with %s " % file_name)
            out.seek(0)
            file_id = self._app.media.put(out, filename=file_name, content_type=content_type, metadata=metadata)
            doc["mimetype"] = content_type
            doc["filemeta"] = decode_metadata(metadata)
            # set the version created to now to bring it to the top of the desk, images can be quite old
            doc["versioncreated"] = utcnow()
            inserted = [file_id]
            file_type = content_type.split("/")[0]
            rendition_spec = self._app.config["RENDITIONS"]["picture"]

            renditions = generate_renditions(
                out, file_id, inserted, file_type, content_type, rendition_spec, self.url_for_media
            )
            doc["renditions"] = renditions
            doc["renditions"]["original_source"] = source_ref
        except Exception as io:
            logger.exception(io)
            for file_id in inserted:
                delete_file_on_error(doc, file_id)

        return doc
    def create(self, docs):
        """Apply transformation requested in 'edit'"""
        ids = []
        archive = get_resource_service('archive')

        for idx, doc in enumerate(docs):
            # first we get item and requested edit operations
            try:
                item = doc.pop('item')
            except KeyError:
                try:
                    item_id = doc.pop('item_id')
                except KeyError:
                    raise errors.SuperdeskApiError.badRequestError('either item or item_id must be specified')
            else:
                item_id = item[config.ID_FIELD]

            item = next(archive.find({'_id': item_id}))
            edit = doc.pop('edit')

            # now we retrieve and load current original media
            rendition = item['renditions']['original']
            media_id = rendition['media']
            media = current_app.media.get(media_id)
            out = im = Image.open(media)

            # we apply all requested operations on original media
            for operation, param in edit.items():
                try:
                    out = self.transform(out, operation, param)
                except ValueError:
                    # if the operation can't be applied just ignore it
                    logger.warning('failed to apply operation: {operation} {param} for media {id}'.format(
                        operation=operation,
                        param=param,
                        id=media_id))
            buf = BytesIO()
            out.save(buf, format=im.format)

            # we set metadata
            buf.seek(0)
            content_type = rendition['mimetype']
            ext = os.path.splitext(rendition['href'])[1]
            filename = str(uuid.uuid4()) + ext

            # and save transformed media in database
            media_id = current_app.media.put(buf, filename=filename, content_type=content_type)

            # now we recreate other renditions based on transformed original media
            buf.seek(0)
            renditions = generate_renditions(buf,
                                             media_id,
                                             [],
                                             'image',
                                             content_type,
                                             get_renditions_spec(),
                                             current_app.media.url_for_media)

            # we update item in db, and the item we'll return to client
            # we keep old renditions in GridFS for history references
            updates = {'renditions': renditions}
            ids.append(item_id)
            archive.update(item_id, updates, item)
            item.update(updates)

            docs[idx] = item

        return [ids]
Example #43
0
    def find_one_raw(self, resource, _id):
        if self._headers is None:
            self.__set_auth_cookie(self._app)

        url = self._app.config['AAP_MM_SEARCH_URL'] + '/Assets/{}'.format(_id)
        r = self._http.request('GET', url, headers=self._headers)
        doc = json.loads(r.data.decode('UTF-8'))
        self._parse_doc(doc)
        if 'fetch_endpoint' in doc:
            del doc['fetch_endpoint']

        # Only if we have credentials can we download the original if the account has that privilege
        if self._username is not None and self._password is not None:
            resolutions = self._get_resolutions(_id)
            if doc[ITEM_TYPE] == CONTENT_TYPE.PICTURE:
                if any(i['Name'] == 'Original' for i in resolutions['Image']):
                    url = self._app.config['AAP_MM_SEARCH_URL'] + '/Assets/{}/Original/download'.format(_id)
                    mime_type = 'image/jpeg'
                else:
                    raise FileNotFoundError
            elif doc[ITEM_TYPE] == CONTENT_TYPE.VIDEO:
                if any(v['Name'] == 'Ipod' for v in resolutions['Video']):
                    url = self._app.config['AAP_MM_SEARCH_URL'] + '/Assets/{}/Ipod/download'.format(_id)
                    mime_type = doc.get('renditions').get('original').get('mimetype')
                else:
                    raise FileNotFoundError
            else:
                raise NotImplementedError
        else:
            if doc[ITEM_TYPE] == CONTENT_TYPE.VIDEO:
                mime_type = doc.get('renditions').get('original').get('mimetype')
            else:
                mime_type = 'image/jpeg'
            url = doc['renditions']['original']['href']

        r = self._http.request('GET', url, headers=self._headers)
        out = BytesIO(r.data)
        file_name, content_type, metadata = process_file_from_stream(out, mime_type)

        inserted = []

        try:
            logger.debug('Going to save media file with %s ' % file_name)
            out.seek(0)
            file_id = self._app.media.put(out, filename=file_name, content_type=content_type, metadata=None)
            doc['mimetype'] = content_type
            doc['filemeta'] = decode_metadata(metadata)
            # set the version created to now to bring it to the top of the desk, images can be quite old
            doc['versioncreated'] = utcnow()
            inserted = [file_id]
            file_type = content_type.split('/')[0]
            rendition_spec = self._app.config['RENDITIONS']['picture']

            renditions = generate_renditions(out, file_id, inserted, file_type,
                                             content_type, rendition_spec,
                                             self.url_for_media, insert_metadata=False)
            doc['renditions'] = renditions
        except Exception as io:
            logger.exception(io)
            for file_id in inserted:
                delete_file_on_error(doc, file_id)

            raise SuperdeskApiError.internalError('Generating renditions failed')

        return doc
Example #44
0
    def find_one_raw(self, resource, _id):
        if self._headers is None:
            self.__set_auth_cookie(self._app)

        url = self._app.config['AAP_MM_SEARCH_URL'] + '/Assets/{}'.format(_id)
        r = self._http.request('GET', url, headers=self._headers)
        doc = json.loads(r.data.decode('UTF-8'))
        self._parse_doc(doc)
        if 'fetch_endpoint' in doc:
            del doc['fetch_endpoint']

        # Only if we have credentials can we download the original if the account has that privilege
        if self._username is not None and self._password is not None:
            resolutions = self._get_resolutions(_id)
            if doc[ITEM_TYPE] == CONTENT_TYPE.PICTURE:
                if any(i['Name'] == 'Original' for i in resolutions['Image']):
                    url = self._app.config[
                        'AAP_MM_SEARCH_URL'] + '/Assets/{}/Original/download'.format(
                            _id)
                    mime_type = 'image/jpeg'
                else:
                    raise FileNotFoundError
            elif doc[ITEM_TYPE] == CONTENT_TYPE.VIDEO:
                if any(v['Name'] == 'Ipod' for v in resolutions['Video']):
                    url = self._app.config[
                        'AAP_MM_SEARCH_URL'] + '/Assets/{}/Ipod/download'.format(
                            _id)
                    mime_type = doc.get('renditions').get('original').get(
                        'mimetype')
                else:
                    raise FileNotFoundError
            else:
                raise NotImplementedError
        else:
            if doc[ITEM_TYPE] == CONTENT_TYPE.VIDEO:
                mime_type = doc.get('renditions').get('original').get(
                    'mimetype')
            else:
                mime_type = 'image/jpeg'
            url = doc['renditions']['original']['href']

        r = self._http.request('GET', url, headers=self._headers)
        out = BytesIO(r.data)
        file_name, content_type, metadata = process_file_from_stream(
            out, mime_type)

        inserted = []

        try:
            logger.debug('Going to save media file with %s ' % file_name)
            out.seek(0)
            file_id = self._app.media.put(out,
                                          filename=file_name,
                                          content_type=content_type,
                                          metadata=None)
            doc['mimetype'] = content_type
            doc['filemeta'] = decode_metadata(metadata)
            # set the version created to now to bring it to the top of the desk, images can be quite old
            doc['versioncreated'] = utcnow()
            inserted = [file_id]
            file_type = content_type.split('/')[0]
            rendition_spec = self._app.config['RENDITIONS']['picture']

            renditions = generate_renditions(out,
                                             file_id,
                                             inserted,
                                             file_type,
                                             content_type,
                                             rendition_spec,
                                             self.url_for_media,
                                             insert_metadata=False)
            doc['renditions'] = renditions
        except Exception as io:
            logger.exception(io)
            for file_id in inserted:
                delete_file_on_error(doc, file_id)

            raise SuperdeskApiError.internalError(
                'Generating renditions failed')

        return doc