diff --git a/comic/admin.py b/comic/admin.py index 073e4a9..5d47eb9 100644 --- a/comic/admin.py +++ b/comic/admin.py @@ -1,8 +1,16 @@ from django.contrib import admin -from comic.models import Setting +from comic.models import Setting, ComicBook, ComicPage # Register your models here. @admin.register(Setting) class SettingAdmin(admin.ModelAdmin): list_display = ('name', 'value') + +@admin.register(ComicBook) +class ComicBookAdmin(admin.ModelAdmin): + list_display = ('file_name', 'last_read_page') + +@admin.register(ComicPage) +class ComicPageAdmin(admin.ModelAdmin): + list_display = ('Comic', 'index', 'page_file_name', 'content_type') \ No newline at end of file diff --git a/comic/models.py b/comic/models.py index 55f4e9e..4aae096 100644 --- a/comic/models.py +++ b/comic/models.py @@ -1,5 +1,6 @@ from django.db import models - +from unrar import rarfile +import zipfile # Create your models here. class Setting(models.Model): @@ -7,13 +8,57 @@ class Setting(models.Model): value = models.TextField() def __str__(self): - return '"%s":"%s"' % (self.name, self.value) + def __unicode__(self): + return self.__str__() + class ComicBook(models.Model): file_name = models.CharField(max_length=100, unique=True) last_read_page = models.IntegerField() + class Comic: + def __init__(self): + self.name = '' + self.index = 0 + class Navigation: + def __init__(self): + self.next_index = 0 + self.next_path = '' + self.prev_index = 0 + self.prev_path = '' + self.cur_index = 0 + self.cur_path = '' + def __str__(self): + return self.file_name + def get_image(self, archive_path, page): + try: + archive = rarfile.RarFile(archive_path) + except rarfile.BadRarFile: + archive = zipfile.ZipFile(archive_path) + except zipfile.BadZipfile: + return False + page_obj = ComicPage.objects.get(Comic=self, index=page) + + return (archive.open(page_obj.page_file_name), page_obj.content_type) + + def nav(self, comic_path, page): + out = self.Navigation() + out.cur_index = page + out.cur_path = comic_path + out.prev_index = page - 1 + out.next_index = page + 1 + out.prev_path = comic_path + out.next_path = comic_path + return out + def pages(self): + out = [] + for item in ComicPage.objects.filter(Comic=self).order_by('index'): + i = self.Comic() + i.name = item.page_file_name + i.index = item.index + out.append(i) + return out class ComicPage(models.Model): Comic = models.ForeignKey(ComicBook) index = models.IntegerField() diff --git a/comic/templates/comic/read_comic.html b/comic/templates/comic/read_comic.html index 114d14e..bce1ef8 100644 --- a/comic/templates/comic/read_comic.html +++ b/comic/templates/comic/read_comic.html @@ -11,25 +11,25 @@ {% block content %}

- - + +
- Prev - {% if pages %} + Prev + {% if book.pages %}
- +
{% else %} -

No comics.

+ {% endif %} - Next + Next
{% endblock %} \ No newline at end of file diff --git a/comic/urls.py b/comic/urls.py index a103f59..567be5c 100644 --- a/comic/urls.py +++ b/comic/urls.py @@ -4,9 +4,9 @@ from . import views urlpatterns = [ url(r'^$', views.index, name='index'), - url(r'^(?P[\w=]+)\/$', views.index, name='index'), - url(r'^read\/(?P[\w=]+)\/(?P[0-9]+)\/$', views.read_comic, name='read_comic'), - url(r'^read\/(?P[\w=]+)\/(?P[0-9]+)\/img$', views.get_image, name='get_image'), + url(r'^(?P[\w]+)\/$', views.index, name='index'), + url(r'^read\/(?P[\w]+)\/(?P[0-9]+)\/$', views.read_comic, name='read_comic'), + url(r'^read\/(?P[\w]+)\/(?P[0-9]+)\/img$', views.get_image, name='get_image'), url(r"^file\/(?P[0-9]+)\/(?P[\w.\s'\(\)\-]+)\/$", views.read_comic, name='read_comic'), url(r"^file\/(?P[0-9]+)\/(?P[\w.\s'\(\)\-]+)\/img$", views.get_image, name='get_image'), ] \ No newline at end of file diff --git a/comic/util.py b/comic/util.py index a6aba16..57a776d 100644 --- a/comic/util.py +++ b/comic/util.py @@ -1,4 +1,7 @@ from django.utils.http import urlsafe_base64_encode +from comic.models import ComicBook, ComicPage +from unrar import rarfile +import zipfile from os import path import os @@ -11,6 +14,7 @@ class Breadcrumb: def __str__(self): return self.name + class DirFile: def __init__(self): self.name = '' @@ -22,6 +26,54 @@ class DirFile: def __str__(self): return self.name + + +def process_comic_book(base_dir, comic_path, comic_file_name): + try: + cbx = rarfile.RarFile(path.join(base_dir.value, comic_path)) + except rarfile.BadRarFile: + cbx = zipfile.ZipFile(path.join(base_dir.value, comic_path)) + except zipfile.BadZipfile: + return False + + book = ComicBook(file_name=comic_file_name, + last_read_page=0) + book.save() + i = 0 + for f in cbx.namelist(): + ext = f.lower()[-3:] + if ext in ['jpg', 'jpeg']: + page = ComicPage(Comic=book, + index=i, + page_file_name=f, + content_type='image/jpeg') + page.save() + i += 1 + elif ext == 'png': + page = ComicPage(Comic=book, + index=i, + page_file_name=f, + content_type='image/png') + page.save() + i += 1 + elif ext == 'bmp': + page = ComicPage(Comic=book, + index=i, + page_file_name=f, + content_type='image/bmp') + page.save() + i += 1 + elif ext == 'gif': + page = ComicPage(Comic=book, + index=i, + page_file_name=f, + content_type='image/gif') + page.save() + i += 1 + + return book + + def generate_breadcrumbs(comic_path): output = [Breadcrumb()] prefix = '/comic/' @@ -33,11 +85,12 @@ def generate_breadcrumbs(comic_path): continue bc = Breadcrumb() bc.name = item - bc.url = prefix + urlsafe_base64_encode(item) - output.append(bc) last = path.join(last, item) + bc.url = prefix + urlsafe_base64_encode(last) + output.append(bc) return output + def generate_directory(base_dir, comic_path): files = [] for fn in os.listdir(path.join(base_dir.value, comic_path)): @@ -52,4 +105,4 @@ def generate_directory(base_dir, comic_path): df.icon = 'glyphicon-book' df.location = urlsafe_base64_encode(path.join(comic_path, fn)) files.append(df) - return files \ No newline at end of file + return files diff --git a/comic/views.py b/comic/views.py index 3370fda..41ddbb0 100644 --- a/comic/views.py +++ b/comic/views.py @@ -1,25 +1,13 @@ from django.http import HttpResponse -from django.template import RequestContext, loader +from django.template import RequestContext from django.utils.http import urlsafe_base64_decode from django.shortcuts import render -from comic.models import Setting -from util import generate_breadcrumbs, generate_directory +from comic.models import Setting, ComicBook +from util import generate_breadcrumbs, generate_directory, process_comic_book -from unrar import rarfile -from zipfile import ZipFile from os import path -class Comic: - def __init__(self): - self.name = '' - self.index = 0 -class Navigation: - def __init__(self): - self.next = 0 - self.prev = 0 - self.cur = 0 - def index(request, comic_path=''): base_dir = Setting.objects.get(name='BASE_DIR') comic_path = urlsafe_base64_decode(comic_path) @@ -33,30 +21,21 @@ def index(request, comic_path=''): def read_comic(request, comic_path, page): - encoded = comic_path - comic_path = urlsafe_base64_decode(comic_path) - breadcrumbs = generate_breadcrumbs(comic_path) base_dir = Setting.objects.get(name='BASE_DIR') - if comic_path.lower().endswith('cbr'): - cbx = rarfile.RarFile(path.join(base_dir.value, comic_path)) - elif comic_path.lower().endswith('cbz'): - cbx = ZipFile(path.join(base_dir.value, comic_path)) - nav = Navigation() page = int(page) - nav.cur = page - nav.next = page + 1 - nav.prev = page - 1 - pages = [] - for idx, name in enumerate(cbx.namelist()): - comic = Comic() - comic.name = name - comic.index = idx - pages.append(comic) + decoded_path = urlsafe_base64_decode(comic_path) + breadcrumbs = generate_breadcrumbs(decoded_path) + _, comic_file_name = path.split(decoded_path) + try: + book = ComicBook.objects.get(file_name=comic_file_name) + except ComicBook.DoesNotExist: + book = process_comic_book(base_dir, decoded_path, comic_file_name) + book.last_read_page = page + book.save() context = RequestContext(request, { - 'pages': pages, - 'file_name': encoded, - 'orig_file_name': pages[nav.cur].name, - 'nav': nav, + 'book': book, + 'orig_file_name': book.pages()[page].name, + 'nav': book.nav(comic_path, page), 'breadcrumbs': breadcrumbs, }) return render(request, 'comic/read_comic.html', context) @@ -64,28 +43,13 @@ def read_comic(request, comic_path, page): def get_image(request, comic_path, page): base_dir = Setting.objects.get(name='BASE_DIR') - comic_path = urlsafe_base64_decode(comic_path) - if comic_path.lower().endswith('cbr'): - cbx = rarfile.RarFile(path.join(base_dir.value, comic_path)) - elif comic_path.lower().endswith('cbz'): - cbx = ZipFile(path.join(base_dir.value, comic_path)) page = int(page) - page_file = cbx.namelist()[page] - file_name = str(page_file).lower() - if file_name.endswith('jpg') or file_name.endswith('jpeg'): - content = 'image/JPEG' - elif file_name.endswith('png'): - content = 'image/png' - elif file_name.endswith('bmp'): - content = 'image/bmp' - elif file_name.endswith('gif'): - content = 'image/gif' - else: - content = 'text/plain' + decoded_path = urlsafe_base64_decode(comic_path) + _, comic_file_name = path.split(decoded_path) try: - img = cbx.open(file) - except KeyError: - img = cbx.open(page_file) + book = ComicBook.objects.get(file_name=comic_file_name) + except ComicBook.DoesNotExist: + book = process_comic_book(base_dir, decoded_path, comic_file_name) + full_path = path.join(base_dir.value, decoded_path) + img, content = book.get_image(full_path, page) return HttpResponse(img.read(), content_type=content) - -