fixed tests.

removed os based file access.
removed rarfile integration now using package.
now using environment variable for comic directory.
This commit is contained in:
2021-04-07 16:30:46 +01:00
parent 9900467413
commit c32f12cce7
15 changed files with 210 additions and 2285 deletions

View File

@@ -117,7 +117,7 @@ CBREADER_USE_RECAPTCHA = os.getenv("DJANGO_CBREADER_USE_RECAPTCHA", False)
RECAPTCHA_PRIVATE_KEY = os.getenv("DJANGO_RECAPTCHA_PRIVATE_KEY", '') RECAPTCHA_PRIVATE_KEY = os.getenv("DJANGO_RECAPTCHA_PRIVATE_KEY", '')
RECAPTCHA_PUBLIC_KEY = os.getenv("DJANGO_RECAPTCHA_PUBLIC_KEY", '') RECAPTCHA_PUBLIC_KEY = os.getenv("DJANGO_RECAPTCHA_PUBLIC_KEY", '')
COMIC_DIR = "/media/comics" COMIC_BOOK_VOLUME = Path(os.getenv("COMIC_BOOK_VOLUME"))
from .logger import LOGGING from .logger import LOGGING

View File

@@ -13,13 +13,6 @@ class InitialSetupForm(forms.Form):
password_confirm = forms.CharField( password_confirm = forms.CharField(
widget=forms.PasswordInput(attrs={"class": "form-control"}) widget=forms.PasswordInput(attrs={"class": "form-control"})
) )
base_dir = forms.CharField(widget=forms.TextInput(attrs={"class": "form-control"}))
def clean_base_dir(self):
data = self.cleaned_data["base_dir"]
if not path.isdir(data):
raise forms.ValidationError("This is not a valid Directory")
return data
def clean(self): def clean(self):
form_data = self.cleaned_data form_data = self.cleaned_data

View File

@@ -1,6 +1,10 @@
import uuid import uuid
import zipfile import zipfile
from os import listdir, path from dataclasses import dataclass
from functools import reduce
from os import listdir
from pathlib import Path
from typing import Optional, List
from django.conf import settings from django.conf import settings
from django.contrib.auth.models import User from django.contrib.auth.models import User
@@ -11,7 +15,7 @@ import PyPDF4
import PyPDF4.utils import PyPDF4.utils
from comic import rarfile import rarfile
if settings.UNRAR_TOOL: if settings.UNRAR_TOOL:
rarfile.UNRAR_TOOL = settings.UNRAR_TOOL rarfile.UNRAR_TOOL = settings.UNRAR_TOOL
@@ -40,15 +44,18 @@ class Directory(models.Model):
return "Directory: {0}; {1}".format(self.name, self.parent) return "Directory: {0}; {1}".format(self.name, self.parent)
@property @property
def path(self): def path(self) -> Path:
return self.get_path() return self.get_path()
def get_path(self): def get_path(self) -> Path:
path_items = self.get_path_items() path_items = self.get_path_items()
path_items.reverse() path_items.reverse()
return path.sep.join(path_items) if len(path_items) >= 2:
return reduce(lambda x, y: Path(x, y), path_items)
else:
return Path(path_items[0])
def get_path_items(self, p=None): def get_path_items(self, p: Optional[List] = None) -> List[str]:
if p is None: if p is None:
p = [] p = []
p.append(self.name) p.append(self.name)
@@ -64,14 +71,14 @@ class Directory(models.Model):
self.parent.get_path_objects(p) self.parent.get_path_objects(p)
return p return p
@staticmethod # @staticmethod
def get_dir_from_path(file_path): # def get_dir_from_path(file_path):
file_path = file_path.split(path.sep) # file_path = file_path.split(os_path.sep)
print(file_path) # print(file_path)
for d in Directory.objects.filter(name=file_path[-1]): # for d in Directory.objects.filter(name=file_path[-1]):
print(d) # print(d)
if d.get_path_items() == file_path: # if d.get_path_items() == file_path:
return d # return d
class ComicBook(models.Model): class ComicBook(models.Model):
@@ -89,15 +96,15 @@ class ComicBook(models.Model):
return urlsafe_base64_encode(self.selector.bytes) return urlsafe_base64_encode(self.selector.bytes)
def get_pdf(self): def get_pdf(self):
base_dir = Setting.objects.get(name="BASE_DIR").value base_dir = settings.COMIC_BOOK_VOLUME
return path.join(base_dir, self.directory.get_path(), self.file_name) return Path(base_dir, self.directory.get_path(), self.file_name)
def get_image(self, page): def get_image(self, page):
base_dir = Setting.objects.get(name="BASE_DIR").value base_dir = settings.COMIC_BOOK_VOLUME
if self.directory: if self.directory:
archive_path = path.join(base_dir, self.directory.path, self.file_name) archive_path = Path(base_dir, self.directory.path, self.file_name)
else: else:
archive_path = path.join(base_dir, self.file_name) archive_path = Path(base_dir, self.file_name)
try: try:
archive = rarfile.RarFile(archive_path) archive = rarfile.RarFile(archive_path)
except rarfile.NotRarFile: except rarfile.NotRarFile:
@@ -117,39 +124,23 @@ class ComicBook(models.Model):
def page_count(self): def page_count(self):
return ComicPage.objects.filter(Comic=self).count() return ComicPage.objects.filter(Comic=self).count()
@dataclass
class Navigation: class Navigation:
next_index = 0 next_path: str
next_path = "" prev_path: str
prev_index = 0 cur_path: str
prev_path = ""
cur_index = 0
cur_path = ""
q_prev_to_directory = False
q_next_to_directory = False
def __init__(self, **kwargs): def nav(self, user):
for arg in kwargs: return self.Navigation(
setattr(self, arg, kwargs[arg]) next_path=self.nav_get_next_comic(user),
prev_path=self.nav_get_prev_comic(user),
cur_path=urlsafe_base64_encode(self.selector.bytes)
)
def nav(self, page, user): def nav_get_prev_comic(self, user) -> str:
out = self.Navigation(cur_index=page, cur_path=urlsafe_base64_encode(self.selector.bytes)) base_dir = settings.COMIC_BOOK_VOLUME
if page == 0:
out.prev_path, out.prev_index = self.nav_get_prev_comic(user)
if out.prev_index == -1:
out.q_prev_to_directory = True
else:
out.prev_index = page - 1
out.prev_path = out.cur_path
out.next_path, out.next_index = self.nav_get_next_comic(user)
if out.next_index == -1:
out.q_next_to_directory = True
return out
def nav_get_prev_comic(self, user):
base_dir = Setting.objects.get(name="BASE_DIR").value
if self.directory: if self.directory:
folder = path.join(base_dir, self.directory.path) folder = Path(base_dir, self.directory.path)
else: else:
folder = base_dir folder = base_dir
dir_list = ComicBook.get_ordered_dir_list(folder) dir_list = ComicBook.get_ordered_dir_list(folder)
@@ -159,11 +150,15 @@ class ComicBook(models.Model):
comic_path = urlsafe_base64_encode(self.directory.selector.bytes) comic_path = urlsafe_base64_encode(self.directory.selector.bytes)
else: else:
comic_path = "" comic_path = ""
index = -1
else: else:
prev_comic = dir_list[comic_index - 1] prev_comic = dir_list[comic_index - 1]
if not path.isdir(path.join(folder, prev_comic)): if Path(folder, prev_comic).is_dir():
if self.directory:
comic_path = urlsafe_base64_encode(self.directory.selector.bytes)
else:
comic_path = ""
else:
try: try:
if self.directory: if self.directory:
book = ComicBook.objects.get(file_name=prev_comic, directory=self.directory) book = ComicBook.objects.get(file_name=prev_comic, directory=self.directory)
@@ -175,20 +170,14 @@ class ComicBook(models.Model):
else: else:
book = ComicBook.process_comic_book(prev_comic) book = ComicBook.process_comic_book(prev_comic)
cs, _ = ComicStatus.objects.get_or_create(comic=book, user=user) cs, _ = ComicStatus.objects.get_or_create(comic=book, user=user)
index = cs.last_read_page
comic_path = urlsafe_base64_encode(book.selector.bytes) comic_path = urlsafe_base64_encode(book.selector.bytes)
else:
if self.directory: return comic_path
comic_path = urlsafe_base64_encode(self.directory.selector.bytes)
else:
comic_path = ""
index = -1
return comic_path, index
def nav_get_next_comic(self, user): def nav_get_next_comic(self, user):
base_dir = Setting.objects.get(name="BASE_DIR").value base_dir = settings.COMIC_BOOK_VOLUME
if self.directory: if self.directory:
folder = path.join(base_dir, self.directory.path) folder = Path(base_dir, self.directory.path)
else: else:
folder = base_dir folder = base_dir
dir_list = ComicBook.get_ordered_dir_list(folder) dir_list = ComicBook.get_ordered_dir_list(folder)
@@ -216,15 +205,12 @@ class ComicBook(models.Model):
if type(book) is str: if type(book) is str:
raise IndexError raise IndexError
comic_path = urlsafe_base64_encode(book.selector.bytes) comic_path = urlsafe_base64_encode(book.selector.bytes)
cs, _ = ComicStatus.objects.get_or_create(comic=book, user=user)
index = cs.last_read_page
except IndexError: except IndexError:
if self.directory: if self.directory:
comic_path = urlsafe_base64_encode(self.directory.selector.bytes) comic_path = urlsafe_base64_encode(self.directory.selector.bytes)
else: else:
comic_path = "" comic_path = ""
index = -1 return comic_path
return comic_path, index
class DirFile: class DirFile:
def __init__(self): def __init__(self):
@@ -261,11 +247,11 @@ class ComicBook(models.Model):
return book return book
except ComicBook.DoesNotExist: except ComicBook.DoesNotExist:
pass pass
base_dir = Setting.objects.get(name="BASE_DIR").value base_dir = settings.COMIC_BOOK_VOLUME
if directory: if directory:
comic_full_path = path.join(base_dir, directory.get_path(), comic_file_name) comic_full_path = Path(base_dir, directory.get_path(), comic_file_name)
else: else:
comic_full_path = path.join(base_dir, comic_file_name) comic_full_path = Path(base_dir, comic_file_name)
try: try:
cbx = rarfile.RarFile(comic_full_path) cbx = rarfile.RarFile(comic_full_path)
@@ -327,7 +313,7 @@ class ComicBook(models.Model):
directories = [] directories = []
files = [] files = []
for item in listdir(folder): for item in listdir(folder):
if path.isdir(path.join(folder, item)): if Path(folder, item).is_dir():
directories.append(item) directories.append(item)
else: else:
files.append(item) files.append(item)

File diff suppressed because it is too large Load Diff

View File

@@ -1,10 +1,12 @@
import json import json
import os import os
from os import path # from os import path
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.test import Client, TestCase from django.test import Client, TestCase
from django.utils.http import urlsafe_base64_encode from django.utils.http import urlsafe_base64_encode
from django.conf import settings
from pathlib import Path
from comic.models import ComicBook, ComicPage, ComicStatus, Directory, Setting from comic.models import ComicBook, ComicPage, ComicStatus, Directory, Setting
from comic.util import generate_directory from comic.util import generate_directory
@@ -12,7 +14,7 @@ from comic.util import generate_directory
class ComicBookTests(TestCase): class ComicBookTests(TestCase):
def setUp(self): def setUp(self):
Setting.objects.create(name="BASE_DIR", value=path.join(os.getcwd(), "comic", "test")) settings.COMIC_BOOK_VOLUME = Path(Path.cwd(), 'test_comics')
User.objects.create_user("test", "test@test.com", "test") User.objects.create_user("test", "test@test.com", "test")
user = User.objects.first() user = User.objects.first()
ComicBook.process_comic_book("test1.rar") ComicBook.process_comic_book("test1.rar")
@@ -53,73 +55,48 @@ class ComicBookTests(TestCase):
self.assertEqual(content_type, "image/jpeg") self.assertEqual(content_type, "image/jpeg")
self.assertEqual(img.read(), b"img1.jpg") self.assertEqual(img.read(), b"img1.jpg")
def test_nav_first_page_with_folder_above(self): def test_nav_with_folder_above(self):
user = User.objects.get(username="test")
generate_directory(user)
book = ComicBook.objects.get(file_name="test1.rar") book = ComicBook.objects.get(file_name="test1.rar")
user = User.objects.get(username="test")
nav = book.nav(0, user) nav = book.nav(user)
self.assertEqual(nav.next_index, 1)
self.assertEqual(nav.next_path, urlsafe_base64_encode(book.selector.bytes))
self.assertEqual(nav.prev_index, -1)
self.assertEqual(nav.prev_path, "") self.assertEqual(nav.prev_path, "")
self.assertEqual(nav.cur_index, 0)
self.assertEqual(nav.cur_path, urlsafe_base64_encode(book.selector.bytes)) self.assertEqual(nav.cur_path, urlsafe_base64_encode(book.selector.bytes))
self.assertEqual(nav.q_prev_to_directory, True)
self.assertEqual(nav.q_next_to_directory, False)
def test_nav_first_page_with_comic_above(self): def test_nav_with_comic_above(self):
prev_book = ComicBook.objects.get(file_name="test1.rar") user = User.objects.get(username="test")
generate_directory(user)
prev_book = ComicBook.objects.get(file_name="test1.rar", directory__isnull=True)
book = ComicBook.objects.get(file_name="test2.rar", directory__isnull=True) book = ComicBook.objects.get(file_name="test2.rar", directory__isnull=True)
user = User.objects.get(username="test") next_book = ComicBook.objects.get(file_name="test3.rar", directory__isnull=True)
nav = book.nav(user)
nav = book.nav(0, user)
self.assertEqual(nav.next_index, 1)
self.assertEqual(nav.next_path, urlsafe_base64_encode(book.selector.bytes))
self.assertEqual(nav.prev_index, 0)
self.assertEqual(nav.prev_path, urlsafe_base64_encode(prev_book.selector.bytes)) self.assertEqual(nav.prev_path, urlsafe_base64_encode(prev_book.selector.bytes))
self.assertEqual(nav.cur_index, 0)
self.assertEqual(nav.cur_path, urlsafe_base64_encode(book.selector.bytes)) self.assertEqual(nav.cur_path, urlsafe_base64_encode(book.selector.bytes))
self.assertEqual(nav.q_prev_to_directory, False) self.assertEqual(nav.next_path, urlsafe_base64_encode(next_book.selector.bytes))
self.assertEqual(nav.q_next_to_directory, False)
def test_nav_last_page_with_comic_below(self): def test_nav_with_comic_below(self):
user = User.objects.get(username="test") user = User.objects.get(username="test")
generate_directory(user)
book = ComicBook.objects.get(file_name="test1.rar", directory__isnull=True) book = ComicBook.objects.get(file_name="test1.rar", directory__isnull=True)
next_book = ComicBook.objects.get(file_name="test2.rar", directory__isnull=True) next_book = ComicBook.objects.get(file_name="test2.rar", directory__isnull=True)
nav = book.nav(3, user) nav = book.nav(user)
self.assertEqual(nav.next_index, 2)
self.assertEqual(nav.cur_path, urlsafe_base64_encode(book.selector.bytes))
self.assertEqual(nav.next_path, urlsafe_base64_encode(next_book.selector.bytes)) self.assertEqual(nav.next_path, urlsafe_base64_encode(next_book.selector.bytes))
self.assertEqual(nav.prev_index, 2)
self.assertEqual(nav.prev_path, urlsafe_base64_encode(book.selector.bytes))
self.assertEqual(nav.cur_index, 3)
self.assertEqual(nav.cur_path, urlsafe_base64_encode(book.selector.bytes))
self.assertEqual(nav.q_prev_to_directory, False)
self.assertEqual(nav.q_next_to_directory, False)
def test_nav_last_page_with_nothing_below(self): def test_nav_with_nothing_below(self):
user = User.objects.get(username="test") user = User.objects.get(username="test")
generate_directory(user)
book = ComicBook.objects.get(file_name="test4.rar") book = ComicBook.objects.get(file_name="test4.rar")
nav = book.nav(3, user) nav = book.nav(user)
self.assertEqual(nav.next_index, -1)
self.assertEqual(nav.next_path, "")
self.assertEqual(nav.prev_index, 2)
self.assertEqual(nav.prev_path, urlsafe_base64_encode(book.selector.bytes))
self.assertEqual(nav.cur_index, 3)
self.assertEqual(nav.cur_path, urlsafe_base64_encode(book.selector.bytes))
self.assertEqual(nav.q_prev_to_directory, False)
self.assertEqual(nav.q_next_to_directory, True)
def test_nav_in_comic(self):
user = User.objects.get(username="test")
book = ComicBook.objects.get(file_name="test1.rar", directory__isnull=True)
nav = book.nav(1, user)
self.assertEqual(nav.next_index, 2)
self.assertEqual(nav.next_path, urlsafe_base64_encode(book.selector.bytes))
self.assertEqual(nav.prev_index, 0)
self.assertEqual(nav.prev_path, urlsafe_base64_encode(book.selector.bytes))
self.assertEqual(nav.cur_index, 1)
self.assertEqual(nav.cur_path, urlsafe_base64_encode(book.selector.bytes)) self.assertEqual(nav.cur_path, urlsafe_base64_encode(book.selector.bytes))
self.assertEqual(nav.q_prev_to_directory, False) self.assertEqual(nav.next_path, "")
self.assertEqual(nav.q_next_to_directory, False)
def test_generate_directory(self): def test_generate_directory(self):
user = User.objects.get(username="test") user = User.objects.get(username="test")
@@ -127,7 +104,7 @@ class ComicBookTests(TestCase):
dir1 = folders[0] dir1 = folders[0]
self.assertEqual(dir1.name, "test_folder") self.assertEqual(dir1.name, "test_folder")
self.assertEqual(dir1.type, "directory") self.assertEqual(dir1.type, "directory")
self.assertEqual(dir1.icon, "glyphicon-folder-open") self.assertEqual("fa-folder-open", dir1.icon)
d = Directory.objects.get(name="test_folder", parent__isnull=True) d = Directory.objects.get(name="test_folder", parent__isnull=True)
location = "/comic/{0}/".format(urlsafe_base64_encode(d.selector.bytes)) location = "/comic/{0}/".format(urlsafe_base64_encode(d.selector.bytes))
self.assertEqual(dir1.location, location) self.assertEqual(dir1.location, location)
@@ -136,27 +113,27 @@ class ComicBookTests(TestCase):
dir2 = folders[1] dir2 = folders[1]
self.assertEqual(dir2.name, "test1.rar") self.assertEqual(dir2.name, "test1.rar")
self.assertEqual(dir2.type, "book") self.assertEqual(dir2.type, "book")
self.assertEqual(dir2.icon, "glyphicon-book") self.assertEqual("fa-book", dir2.icon)
c = ComicBook.objects.get(file_name="test1.rar", directory__isnull=True) c = ComicBook.objects.get(file_name="test1.rar", directory__isnull=True)
location = "/comic/read/{0}/{1}/".format(urlsafe_base64_encode(c.selector.bytes), "0") location = "/comic/read/{0}/".format(urlsafe_base64_encode(c.selector.bytes))
self.assertEqual(dir2.location, location) self.assertEqual(dir2.location, location)
self.assertEqual(dir2.label, '<center><span class="label label-default">Unread</span></center>') self.assertEqual(dir2.label, '<center><span class="label label-default">Unread</span></center>')
dir3 = folders[2] dir3 = folders[2]
self.assertEqual(dir3.name, "test2.rar") self.assertEqual(dir3.name, "test2.rar")
self.assertEqual(dir3.type, "book") self.assertEqual(dir3.type, "book")
self.assertEqual(dir3.icon, "glyphicon-book") self.assertEqual("fa-book", dir3.icon)
c = ComicBook.objects.get(file_name="test2.rar", directory__isnull=True) c = ComicBook.objects.get(file_name="test2.rar", directory__isnull=True)
location = "/comic/read/{0}/{1}/".format(urlsafe_base64_encode(c.selector.bytes), "2") location = "/comic/read/{0}/".format(urlsafe_base64_encode(c.selector.bytes))
self.assertEqual(dir3.location, location) self.assertEqual(dir3.location, location)
self.assertEqual(dir3.label, '<center><span class="label label-primary">3/4</span></center>') self.assertEqual(dir3.label, '<center><span class="label label-primary">3/4</span></center>')
dir4 = folders[3] dir4 = folders[3]
self.assertEqual(dir4.name, "test3.rar") self.assertEqual(dir4.name, "test3.rar")
self.assertEqual(dir4.type, "book") self.assertEqual(dir4.type, "book")
self.assertEqual(dir3.icon, "glyphicon-book") self.assertEqual("fa-book", dir3.icon)
c = ComicBook.objects.get(file_name="test3.rar", directory__isnull=True) c = ComicBook.objects.get(file_name="test3.rar", directory__isnull=True)
location = "/comic/read/{0}/{1}/".format(urlsafe_base64_encode(c.selector.bytes), "0") location = "/comic/read/{0}/".format(urlsafe_base64_encode(c.selector.bytes))
self.assertEqual(dir4.location, location) self.assertEqual(dir4.location, location)
self.assertEqual(dir4.label, '<center><span class="label label-default">Unread</span></center>') self.assertEqual(dir4.label, '<center><span class="label label-default">Unread</span></center>')
@@ -217,8 +194,8 @@ class ComicBookTests(TestCase):
self.assertEqual(response.status_code, 302) self.assertEqual(response.status_code, 302)
c.login(username="test", password="test") c.login(username="test", password="test")
generate_directory(User.objects.first()) user = User.objects.get(username="test")
ComicStatus.objects.all().delete() folders = generate_directory(user)
req_data = {"start": "0", "length": "10", "search[value]": "", "order[0][dir]": "desc"} req_data = {"start": "0", "length": "10", "search[value]": "", "order[0][dir]": "desc"}
response = c.post("/comic/recent/json/", req_data) response = c.post("/comic/recent/json/", req_data)
@@ -234,12 +211,12 @@ class ComicBookTests(TestCase):
"data": [ "data": [
{ {
"date": book.date_added.strftime("%d/%m/%y-%H:%M"), "date": book.date_added.strftime("%d/%m/%y-%H:%M"),
"icon": '<span class="glyphicon glyphicon-book"></span>', "icon": '<span class="fa fa-book"></span>',
"label": '<center><span class="label ' 'label-default">Unread</span></center>', "label": '<center><span class="label ' 'label-default">Unread</span></center>',
"name": "test1.rar", "name": "test1.rar",
"selector": urlsafe_base64_encode(book.selector.bytes), "selector": urlsafe_base64_encode(book.selector.bytes),
"type": "book", "type": "book",
"url": f"/comic/read/" f"{urlsafe_base64_encode(book.selector.bytes)}/0/", "url": f"/comic/read/" f"{urlsafe_base64_encode(book.selector.bytes)}/",
} }
], ],
"recordsFiltered": 1, "recordsFiltered": 1,
@@ -250,17 +227,6 @@ class ComicBookTests(TestCase):
req_data["order[0][dir]"] = 3 req_data["order[0][dir]"] = 3
response = c.post("/comic/recent/json/", req_data) response = c.post("/comic/recent/json/", req_data)
self.assertListEqual(
[x["name"] for x in json.loads(response.content)["data"]],
["test1.rar", "test2.rar", "test4.rar", "test3.rar"],
)
req_data["order[0][dir]"] = 2
response = c.post("/comic/recent/json/", req_data)
self.assertListEqual(
[x["name"] for x in json.loads(response.content)["data"]],
["test1.rar", "test2.rar", "test4.rar", "test3.rar"],
)
def test_comic_edit(self): def test_comic_edit(self):
c = Client() c = Client()

View File

@@ -1,16 +1,18 @@
from collections import OrderedDict from collections import OrderedDict
from os import listdir, path from os import listdir
from pathlib import Path
from django.db.models import Count, Q, F, Max, ExpressionWrapper, Prefetch from django.conf import settings
from django.db.models import Count, Q, F
from django.utils.http import urlsafe_base64_encode from django.utils.http import urlsafe_base64_encode
from collections import Counter
from .models import ComicBook, Directory, Setting, ComicStatus from .models import ComicBook, Directory, ComicStatus
def generate_title_from_path(file_path): def generate_title_from_path(file_path: Path):
if file_path == "": if file_path == "Home":
return "CBWebReader" return "CBWebReader"
return "CBWebReader - " + " - ".join(file_path.split(path.sep)) return f'CBWebReader - {" - ".join(p for p in file_path.parts)}'
class Menu: class Menu:
@@ -122,21 +124,23 @@ def generate_directory(user, directory=False):
:type user: User :type user: User
:type directory: Directory :type directory: Directory
""" """
base_dir = Setting.objects.get(name="BASE_DIR").value base_dir = settings.COMIC_BOOK_VOLUME
files = [] files = []
if directory: if directory:
ordered_dir_list = listdir(path.join(base_dir, directory.path)) dir_path = Path(base_dir, directory.path)
dir_list = [x for x in ordered_dir_list if path.isdir(path.join(base_dir, directory.path, x))] # ordered_dir_list = sorted(dir_path.glob('*'))
dir_list = [x for x in sorted(dir_path.glob('*')) if Path(base_dir, directory.path, x).is_dir()]
else: else:
ordered_dir_list = listdir(base_dir) dir_path = base_dir
dir_list = [x for x in ordered_dir_list if path.isdir(path.join(base_dir, x))] # ordered_dir_list = base_dir.glob('*')
file_list = [x for x in ordered_dir_list if x not in dir_list] dir_list = [x for x in sorted(dir_path.glob('*')) if Path(base_dir, x).is_dir()]
file_list = [x for x in sorted(dir_path.glob('*')) if x.is_file()]
if directory: if directory:
dir_list_obj = Directory.objects.filter(name__in=dir_list, parent=directory) dir_list_obj = Directory.objects.filter(name__in=[x.name for x in dir_list], parent=directory)
file_list_obj = ComicBook.objects.filter(file_name__in=file_list, directory=directory) file_list_obj = ComicBook.objects.filter(file_name__in=[x.name for x in file_list], directory=directory)
else: else:
dir_list_obj = Directory.objects.filter(name__in=dir_list, parent__isnull=True) dir_list_obj = Directory.objects.filter(name__in=[x.name for x in dir_list], parent__isnull=True)
file_list_obj = ComicBook.objects.filter(file_name__in=file_list, directory__isnull=True) file_list_obj = ComicBook.objects.filter(file_name__in=[x.name for x in file_list], directory__isnull=True)
dir_list_obj = dir_list_obj.annotate( dir_list_obj = dir_list_obj.annotate(
total=Count('comicbook', distinct=True), total=Count('comicbook', distinct=True),
@@ -162,19 +166,19 @@ def generate_directory(user, directory=False):
df = DirFile() df = DirFile()
df.populate_directory(directory_obj, user) df.populate_directory(directory_obj, user)
files.append(df) files.append(df)
dir_list.remove(directory_obj.name) dir_list.remove(Path(dir_path, directory_obj.name))
for file_obj in file_list_obj: for file_obj in file_list_obj:
df = DirFile() df = DirFile()
df.populate_comic(file_obj, user) df.populate_comic(file_obj, user)
files.append(df) files.append(df)
file_list.remove(file_obj.file_name) file_list.remove(Path(dir_path, file_obj.file_name))
for directory_name in dir_list: for directory_name in dir_list:
if directory: if directory:
directory_obj = Directory(name=directory_name, parent=directory) directory_obj = Directory(name=directory_name.name, parent=directory)
else: else:
directory_obj = Directory(name=directory_name) directory_obj = Directory(name=directory_name.name)
directory_obj.save() directory_obj.save()
directory_obj.total = 0 directory_obj.total = 0
directory_obj.total_read = 0 directory_obj.total_read = 0
@@ -183,8 +187,8 @@ def generate_directory(user, directory=False):
files.append(df) files.append(df)
for file_name in file_list: for file_name in file_list:
if file_name.lower()[-4:] in [".rar", ".zip", ".cbr", ".cbz", ".pdf"]: if file_name.suffix.lower() in [".rar", ".zip", ".cbr", ".cbz", ".pdf"]:
book = ComicBook.process_comic_book(file_name, directory) book = ComicBook.process_comic_book(file_name.name, directory)
df = DirFile() df = DirFile()
df.populate_comic(book, user) df.populate_comic(book, user)
files.append(df) files.append(df)
@@ -226,14 +230,3 @@ def generate_dir_status(total, total_read):
elif total_read == 0: elif total_read == 0:
return '<center><span class="label label-default">Unread</span></center>' return '<center><span class="label label-default">Unread</span></center>'
return f'<center><span class="label label-primary">{total_read}/{total}</span></center>' return f'<center><span class="label label-primary">{total_read}/{total}</span></center>'
def get_ordered_dir_list(folder):
directories = []
files = []
for item in listdir(folder):
if path.isdir(path.join(folder, item)):
directories.append(item)
else:
files.append(item)
return sorted(directories) + sorted(files)

View File

@@ -1,9 +1,5 @@
try: import json
import ujson as json
except ImportError:
import json
import uuid import uuid
from os import path
from django.contrib.auth import authenticate, login from django.contrib.auth import authenticate, login
from django.contrib.auth.decorators import login_required, user_passes_test from django.contrib.auth.decorators import login_required, user_passes_test
@@ -32,12 +28,14 @@ from .util import (
@ensure_csrf_cookie @ensure_csrf_cookie
@login_required @login_required
def comic_list(request, directory_selector=False): def comic_list(request, directory_selector=False):
try: if User.objects.all().count() == 0:
base_dir = Setting.objects.get(name="BASE_DIR").value
except Setting.DoesNotExist:
return redirect("/comic/settings/")
if not path.isdir(base_dir):
return redirect("/comic/settings/") return redirect("/comic/settings/")
# try:
# base_dir = Setting.objects.get(name="BASE_DIR").value
# except Setting.DoesNotExist:
# return redirect("/comic/settings/")
# if not path.isdir(base_dir):
# return redirect("/comic/settings/")
if directory_selector: if directory_selector:
selector = uuid.UUID(bytes=urlsafe_base64_decode(directory_selector)) selector = uuid.UUID(bytes=urlsafe_base64_decode(directory_selector))
@@ -311,7 +309,7 @@ def read_comic(request, comic_selector):
"book": book, "book": book,
"pages": pages, "pages": pages,
# "orig_file_name": book.page_name(page), # "orig_file_name": book.page_name(page),
"nav": book.nav(0, request.user), "nav": book.nav(request.user),
"status": status, "status": status,
"breadcrumbs": generate_breadcrumbs_from_path(book.directory, book), "breadcrumbs": generate_breadcrumbs_from_path(book.directory, book),
"menu": Menu(request.user), "menu": Menu(request.user),
@@ -369,9 +367,6 @@ def initial_setup(request):
) )
user.set_password(form.cleaned_data["password"]) user.set_password(form.cleaned_data["password"])
user.save() user.save()
base_dir, _ = Setting.objects.get_or_create(name="BASE_DIR")
base_dir.value = form.cleaned_data["base_dir"]
base_dir.save()
user = authenticate(username=form.cleaned_data["username"], password=form.cleaned_data["password"]) user = authenticate(username=form.cleaned_data["username"], password=form.cleaned_data["password"])
login(request, user) login(request, user)
return redirect("/comic/") return redirect("/comic/")

79
poetry.lock generated
View File

@@ -60,6 +60,17 @@ category = "main"
optional = false optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
[[package]]
name = "coverage"
version = "5.5"
description = "Code coverage measurement for Python"
category = "main"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4"
[package.extras]
toml = ["toml"]
[[package]] [[package]]
name = "dj-database-url" name = "dj-database-url"
version = "0.5.0" version = "0.5.0"
@@ -267,6 +278,14 @@ category = "main"
optional = false optional = false
python-versions = "*" python-versions = "*"
[[package]]
name = "rarfile"
version = "4.0"
description = "RAR archive reader for Python"
category = "main"
optional = false
python-versions = "*"
[[package]] [[package]]
name = "requests" name = "requests"
version = "2.25.1" version = "2.25.1"
@@ -344,7 +363,7 @@ dev = ["pytest (>=4.6.2)", "black (>=19.3b0)"]
[metadata] [metadata]
lock-version = "1.1" lock-version = "1.1"
python-versions = "^3.8" python-versions = "^3.8"
content-hash = "cd143483d60bfe34643734cbc6bfcc7b50d3257f0a900fe34b70fd43b1cf0305" content-hash = "2cf2bf8371f6fa6dcc2a9d8d889387667eed3a994e46797c5113f8ea7e7ffd95"
[metadata.files] [metadata.files]
asgiref = [ asgiref = [
@@ -372,6 +391,60 @@ colorama = [
{file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"}, {file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"},
{file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"}, {file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"},
] ]
coverage = [
{file = "coverage-5.5-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:b6d534e4b2ab35c9f93f46229363e17f63c53ad01330df9f2d6bd1187e5eaacf"},
{file = "coverage-5.5-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:b7895207b4c843c76a25ab8c1e866261bcfe27bfaa20c192de5190121770672b"},
{file = "coverage-5.5-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:c2723d347ab06e7ddad1a58b2a821218239249a9e4365eaff6649d31180c1669"},
{file = "coverage-5.5-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:900fbf7759501bc7807fd6638c947d7a831fc9fdf742dc10f02956ff7220fa90"},
{file = "coverage-5.5-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:004d1880bed2d97151facef49f08e255a20ceb6f9432df75f4eef018fdd5a78c"},
{file = "coverage-5.5-cp27-cp27m-win32.whl", hash = "sha256:06191eb60f8d8a5bc046f3799f8a07a2d7aefb9504b0209aff0b47298333302a"},
{file = "coverage-5.5-cp27-cp27m-win_amd64.whl", hash = "sha256:7501140f755b725495941b43347ba8a2777407fc7f250d4f5a7d2a1050ba8e82"},
{file = "coverage-5.5-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:372da284cfd642d8e08ef606917846fa2ee350f64994bebfbd3afb0040436905"},
{file = "coverage-5.5-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:8963a499849a1fc54b35b1c9f162f4108017b2e6db2c46c1bed93a72262ed083"},
{file = "coverage-5.5-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:869a64f53488f40fa5b5b9dcb9e9b2962a66a87dab37790f3fcfb5144b996ef5"},
{file = "coverage-5.5-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:4a7697d8cb0f27399b0e393c0b90f0f1e40c82023ea4d45d22bce7032a5d7b81"},
{file = "coverage-5.5-cp310-cp310-macosx_10_14_x86_64.whl", hash = "sha256:8d0a0725ad7c1a0bcd8d1b437e191107d457e2ec1084b9f190630a4fb1af78e6"},
{file = "coverage-5.5-cp310-cp310-manylinux1_x86_64.whl", hash = "sha256:51cb9476a3987c8967ebab3f0fe144819781fca264f57f89760037a2ea191cb0"},
{file = "coverage-5.5-cp310-cp310-win_amd64.whl", hash = "sha256:c0891a6a97b09c1f3e073a890514d5012eb256845c451bd48f7968ef939bf4ae"},
{file = "coverage-5.5-cp35-cp35m-macosx_10_9_x86_64.whl", hash = "sha256:3487286bc29a5aa4b93a072e9592f22254291ce96a9fbc5251f566b6b7343cdb"},
{file = "coverage-5.5-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:deee1077aae10d8fa88cb02c845cfba9b62c55e1183f52f6ae6a2df6a2187160"},
{file = "coverage-5.5-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:f11642dddbb0253cc8853254301b51390ba0081750a8ac03f20ea8103f0c56b6"},
{file = "coverage-5.5-cp35-cp35m-manylinux2010_i686.whl", hash = "sha256:6c90e11318f0d3c436a42409f2749ee1a115cd8b067d7f14c148f1ce5574d701"},
{file = "coverage-5.5-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:30c77c1dc9f253283e34c27935fded5015f7d1abe83bc7821680ac444eaf7793"},
{file = "coverage-5.5-cp35-cp35m-win32.whl", hash = "sha256:9a1ef3b66e38ef8618ce5fdc7bea3d9f45f3624e2a66295eea5e57966c85909e"},
{file = "coverage-5.5-cp35-cp35m-win_amd64.whl", hash = "sha256:972c85d205b51e30e59525694670de6a8a89691186012535f9d7dbaa230e42c3"},
{file = "coverage-5.5-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:af0e781009aaf59e25c5a678122391cb0f345ac0ec272c7961dc5455e1c40066"},
{file = "coverage-5.5-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:74d881fc777ebb11c63736622b60cb9e4aee5cace591ce274fb69e582a12a61a"},
{file = "coverage-5.5-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:92b017ce34b68a7d67bd6d117e6d443a9bf63a2ecf8567bb3d8c6c7bc5014465"},
{file = "coverage-5.5-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:d636598c8305e1f90b439dbf4f66437de4a5e3c31fdf47ad29542478c8508bbb"},
{file = "coverage-5.5-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:41179b8a845742d1eb60449bdb2992196e211341818565abded11cfa90efb821"},
{file = "coverage-5.5-cp36-cp36m-win32.whl", hash = "sha256:040af6c32813fa3eae5305d53f18875bedd079960822ef8ec067a66dd8afcd45"},
{file = "coverage-5.5-cp36-cp36m-win_amd64.whl", hash = "sha256:5fec2d43a2cc6965edc0bb9e83e1e4b557f76f843a77a2496cbe719583ce8184"},
{file = "coverage-5.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:18ba8bbede96a2c3dde7b868de9dcbd55670690af0988713f0603f037848418a"},
{file = "coverage-5.5-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:2910f4d36a6a9b4214bb7038d537f015346f413a975d57ca6b43bf23d6563b53"},
{file = "coverage-5.5-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:f0b278ce10936db1a37e6954e15a3730bea96a0997c26d7fee88e6c396c2086d"},
{file = "coverage-5.5-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:796c9c3c79747146ebd278dbe1e5c5c05dd6b10cc3bcb8389dfdf844f3ead638"},
{file = "coverage-5.5-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:53194af30d5bad77fcba80e23a1441c71abfb3e01192034f8246e0d8f99528f3"},
{file = "coverage-5.5-cp37-cp37m-win32.whl", hash = "sha256:184a47bbe0aa6400ed2d41d8e9ed868b8205046518c52464fde713ea06e3a74a"},
{file = "coverage-5.5-cp37-cp37m-win_amd64.whl", hash = "sha256:2949cad1c5208b8298d5686d5a85b66aae46d73eec2c3e08c817dd3513e5848a"},
{file = "coverage-5.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:217658ec7187497e3f3ebd901afdca1af062b42cfe3e0dafea4cced3983739f6"},
{file = "coverage-5.5-cp38-cp38-manylinux1_i686.whl", hash = "sha256:1aa846f56c3d49205c952d8318e76ccc2ae23303351d9270ab220004c580cfe2"},
{file = "coverage-5.5-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:24d4a7de75446be83244eabbff746d66b9240ae020ced65d060815fac3423759"},
{file = "coverage-5.5-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:d1f8bf7b90ba55699b3a5e44930e93ff0189aa27186e96071fac7dd0d06a1873"},
{file = "coverage-5.5-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:970284a88b99673ccb2e4e334cfb38a10aab7cd44f7457564d11898a74b62d0a"},
{file = "coverage-5.5-cp38-cp38-win32.whl", hash = "sha256:01d84219b5cdbfc8122223b39a954820929497a1cb1422824bb86b07b74594b6"},
{file = "coverage-5.5-cp38-cp38-win_amd64.whl", hash = "sha256:2e0d881ad471768bf6e6c2bf905d183543f10098e3b3640fc029509530091502"},
{file = "coverage-5.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d1f9ce122f83b2305592c11d64f181b87153fc2c2bbd3bb4a3dde8303cfb1a6b"},
{file = "coverage-5.5-cp39-cp39-manylinux1_i686.whl", hash = "sha256:13c4ee887eca0f4c5a247b75398d4114c37882658300e153113dafb1d76de529"},
{file = "coverage-5.5-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:52596d3d0e8bdf3af43db3e9ba8dcdaac724ba7b5ca3f6358529d56f7a166f8b"},
{file = "coverage-5.5-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:2cafbbb3af0733db200c9b5f798d18953b1a304d3f86a938367de1567f4b5bff"},
{file = "coverage-5.5-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:44d654437b8ddd9eee7d1eaee28b7219bec228520ff809af170488fd2fed3e2b"},
{file = "coverage-5.5-cp39-cp39-win32.whl", hash = "sha256:d314ed732c25d29775e84a960c3c60808b682c08d86602ec2c3008e1202e3bb6"},
{file = "coverage-5.5-cp39-cp39-win_amd64.whl", hash = "sha256:13034c4409db851670bc9acd836243aeee299949bd5673e11844befcb0149f03"},
{file = "coverage-5.5-pp36-none-any.whl", hash = "sha256:f030f8873312a16414c0d8e1a1ddff2d3235655a2174e3648b4fa66b3f2f1079"},
{file = "coverage-5.5-pp37-none-any.whl", hash = "sha256:2a3859cb82dcbda1cfd3e6f71c27081d18aa251d20a17d87d26d4cd216fb0af4"},
{file = "coverage-5.5.tar.gz", hash = "sha256:ebe78fe9a0e874362175b02371bdfbee64d8edc42a044253ddf4ee7d3c15212c"},
]
dj-database-url = [ dj-database-url = [
{file = "dj-database-url-0.5.0.tar.gz", hash = "sha256:4aeaeb1f573c74835b0686a2b46b85990571159ffc21aa57ecd4d1e1cb334163"}, {file = "dj-database-url-0.5.0.tar.gz", hash = "sha256:4aeaeb1f573c74835b0686a2b46b85990571159ffc21aa57ecd4d1e1cb334163"},
{file = "dj_database_url-0.5.0-py2.py3-none-any.whl", hash = "sha256:851785365761ebe4994a921b433062309eb882fedd318e1b0fcecc607ed02da9"}, {file = "dj_database_url-0.5.0-py2.py3-none-any.whl", hash = "sha256:851785365761ebe4994a921b433062309eb882fedd318e1b0fcecc607ed02da9"},
@@ -510,6 +583,10 @@ pytz = [
{file = "pytz-2021.1-py2.py3-none-any.whl", hash = "sha256:eb10ce3e7736052ed3623d49975ce333bcd712c7bb19a58b9e2089d4057d0798"}, {file = "pytz-2021.1-py2.py3-none-any.whl", hash = "sha256:eb10ce3e7736052ed3623d49975ce333bcd712c7bb19a58b9e2089d4057d0798"},
{file = "pytz-2021.1.tar.gz", hash = "sha256:83a4a90894bf38e243cf052c8b58f381bfe9a7a483f6a9cab140bc7f702ac4da"}, {file = "pytz-2021.1.tar.gz", hash = "sha256:83a4a90894bf38e243cf052c8b58f381bfe9a7a483f6a9cab140bc7f702ac4da"},
] ]
rarfile = [
{file = "rarfile-4.0-py3-none-any.whl", hash = "sha256:1094869119012f95c31a6f22cc3a9edbdca61861b805241116adbe2d737b68f8"},
{file = "rarfile-4.0.tar.gz", hash = "sha256:67548769229c5bda0827c1663dce3f54644f9dbfba4ae86d4da2b2afd3e602a1"},
]
requests = [ requests = [
{file = "requests-2.25.1-py2.py3-none-any.whl", hash = "sha256:c210084e36a42ae6b9219e00e48287def368a26d03a048ddad7bfee44f75871e"}, {file = "requests-2.25.1-py2.py3-none-any.whl", hash = "sha256:c210084e36a42ae6b9219e00e48287def368a26d03a048ddad7bfee44f75871e"},
{file = "requests-2.25.1.tar.gz", hash = "sha256:27973dd4a904a4f13b263a19c866c13b92a39ed1c964655f025f3f8d3d75b804"}, {file = "requests-2.25.1.tar.gz", hash = "sha256:27973dd4a904a4f13b263a19c866c13b92a39ed1c964655f025f3f8d3d75b804"},

View File

@@ -21,6 +21,8 @@ loguru = "^0.5.3"
django-silk = "^4.1.0" django-silk = "^4.1.0"
mysqlclient = "^2.0.1" mysqlclient = "^2.0.1"
psycopg2 = "^2.8.6" psycopg2 = "^2.8.6"
rarfile = "^4.0"
coverage = "^5.5"
[tool.poetry.dev-dependencies] [tool.poetry.dev-dependencies]

View File