From c2586bb61d647426ed713aa564623fce4f0de321 Mon Sep 17 00:00:00 2001 From: j <0x006A@0x2620.org> Date: Wed, 23 Feb 2011 10:52:30 +0100 Subject: [PATCH] add covers --- oxdata/cover/__init__.py | 0 oxdata/cover/admin.py | 10 +++++ oxdata/cover/models.py | 96 ++++++++++++++++++++++++++++++++++++++++ oxdata/cover/urls.py | 6 +++ oxdata/cover/views.py | 18 ++++++++ 5 files changed, 130 insertions(+) create mode 100644 oxdata/cover/__init__.py create mode 100644 oxdata/cover/admin.py create mode 100644 oxdata/cover/models.py create mode 100644 oxdata/cover/urls.py create mode 100644 oxdata/cover/views.py diff --git a/oxdata/cover/__init__.py b/oxdata/cover/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/oxdata/cover/admin.py b/oxdata/cover/admin.py new file mode 100644 index 0000000..a2c0e8a --- /dev/null +++ b/oxdata/cover/admin.py @@ -0,0 +1,10 @@ +# -*- coding: utf-8 -*- +# vi:si:et:sw=4:sts=4:ts=4 + +import models +from django.contrib import admin + +class CoverAdmin(admin.ModelAdmin): + search_fields = ['url', 'isbn'] +admin.site.register(models.Cover, CoverAdmin) + diff --git a/oxdata/cover/models.py b/oxdata/cover/models.py new file mode 100644 index 0000000..dd1b32a --- /dev/null +++ b/oxdata/cover/models.py @@ -0,0 +1,96 @@ +# -*- coding: utf-8 -*- +# vi:si:et:sw=4:sts=4:ts=4 +from __future__ import division + +import os.path +import hashlib + +from django.conf import settings +from django.db import models +from django.db.models import Q +from django.contrib.auth.models import User +from django.core.files.base import ContentFile + +def getCovers(isbn, url_prefix='', limit=lambda x, y: 0.3 < x/y < 1): + covers = {} + if url_prefix.endswith('/'): url_prefix = url_prefix[:-1] + for p in CoverCache.objects.all().filter(isbn=isbn, failed=False).order_by('id'): + if p.site not in covers: + covers[p.site] = [] + cover = p.get() + if cover: + pjson = {} + pjson['url'] = url_prefix + cover._get_url() + pjson['width'] = cover.width + pjson['height'] = cover.height + if p.site not in ['other', 'wikipedia.org'] or limit(cover.width, cover.height): + covers[p.site].append(pjson) + for p in covers.keys(): + if not covers[p]: + del covers[p] + covers = Cover.objects.filter(isbn=isbn).exclude(cover='') + if cover.count() > 0: + covers['local'] = [p.cover.url] + return covers + +def cover_path(url, filename): + h = hashlib.sha1(url).hexdigest() + ext = 'jpg' + if filename.endswith('.png'): + ext = 'png' + name = "%s.%s" % (h, ext) + return os.path.join('covers', h[:2], h[2:4], h[4:6], name) + +class CoverCache(models.Model): + class Meta: + unique_together = ("isbn", "url") + + created = models.DateTimeField(auto_now_add=True) + modified = models.DateTimeField(auto_now=True) + + isbn = models.CharField(max_length=13) + url = models.CharField(max_length=1024) + site = models.CharField(max_length=255) + site_id = models.CharField(max_length=42) + image = models.ImageField(max_length=255, upload_to=lambda i, f: cover_path(i.url.encode('utf-8'), f)) + status = models.CharField(max_length=1024, default='200') + failed = models.BooleanField(default=False) + + def get(self): + if not self.image and not self.failed: + import ox.net + url = self.url.encode('utf-8') + name = hashlib.sha1(url).hexdigest() + try: + data = ox.net.readUrl(url) + self.image.save(name, ContentFile(data)) + except ox.net.urllib2.HTTPError, e: + #import traceback + #print traceback.print_exc() + self.status = e.code + self.failed = True + self.save() + except ox.net.urllib2.URLError, e: + #import traceback + #print traceback.print_exc() + self.status = e.reason + self.failed = True + self.save() + if self.image: + try: + self.image.width + except IOError: + self.image.delete() + except TypeError: + self.failed = True + self.status = "invalid image" + self.image.delete() + return self.image + +class Cover(models.Model): + created = models.DateTimeField(auto_now_add=True) + modified = models.DateTimeField(auto_now=True) + + isbn = models.ForeignKey(MovieId, related_name='cover') + cover = models.ImageField(max_length=255, upload_to=lambda i, f: cover_path('upload/%s' % i.id, f)) + diff --git a/oxdata/cover/urls.py b/oxdata/cover/urls.py new file mode 100644 index 0000000..629466f --- /dev/null +++ b/oxdata/cover/urls.py @@ -0,0 +1,6 @@ +from django.conf.urls.defaults import * + +urlpatterns = patterns('oxdata.cover.views', + (r'^$', 'cover'), +) + diff --git a/oxdata/cover/views.py b/oxdata/cover/views.py new file mode 100644 index 0000000..1c7001f --- /dev/null +++ b/oxdata/cover/views.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# vi:si:et:sw=4:sts=4:ts=4 +import os.path +from django.db import models +from django.db.models import Q +from django.contrib.auth.models import User +from django.shortcuts import render_to_response, get_object_or_404, get_list_or_404 +from django.template import RequestContext + +from oxdjango.shortcuts import render_to_json_response + +import models + +def cover(request): + isbn = request.GET['isbn'] + json = models.getCovers(isbn, request.build_absolute_uri('/')) + return render_to_json_response(json) +