Source

appengine-cdn / mcdn / models.py

Full commit
from __future__ import division

import hashlib

from google.appengine.ext import db
from google.appengine.api.urlfetch import fetch
from google.appengine.api import images

import flask

from mcdn import utils


class BadResponse(Exception):
    pass


class File(db.Model):
    name = db.StringProperty(required=True)
    mimetype = db.StringProperty()
    content = db.BlobProperty()
    etag = db.StringProperty()
    upload_date = db.DateTimeProperty(auto_now_add=True)
    namespace = db.StringProperty()

    @classmethod
    def namespace_objects(cls):
        return cls.all().filter('namespace', utils.subdomain())

    def put(self, *args, **kwargs):
        self.etag = hashlib.md5(self.content).hexdigest()
        self.namespace = utils.subdomain()
        return super(File, self).put(*args, **kwargs)

    def get_absolute_url(self):
        return flask.url_for('serve', name=self.name)

    def update_from_url(self, url):
        response = fetch(url)
        if response.status_code != 200:
            raise BadResponse()

        self.content = response.content
        try:
            self.mimetype = response.headers['Content-Type']
        except KeyError:
            from mcdn.utils import get_mimetype
            self.mimetype = get_mimetype(url)

    def resize(self, width, height, modifier=None):
        img = images.Image(self.content)

        if modifier and modifier:
            if modifier == 'b':
                if img.width > width or img.height > height:
                    img.resize(width, height)
            elif modifier == 'c':
                if width > img.width:
                    img.resize(width=width)
                    img = images.Image(img.execute_transforms())

                if height > img.height:
                    img.resize(height=height)
                    img = images.Image(img.execute_transforms())

                x = (width / img.width) / 2
                y = (height / img.height) / 2
                img.crop(0.5 - x, 0.5 - y, 0.5 + x, 0.5 + y)
        else:
            img.resize(width, height)

        if self.mimetype == 'images/jpeg':
            self.content = img.execute_transforms(output_encoding=images.JPEG, quality=85)
        else:
            self.content = img.execute_transforms(output_encoding=images.PNG)