mirror of
https://github.com/th3r00t/pyShelf.git
synced 2026-04-28 01:59:35 -04:00
488 lines
16 KiB
Python
Executable File
488 lines
16 KiB
Python
Executable File
import json
|
|
import os
|
|
from base64 import b64decode, b64encode
|
|
from pathlib import Path
|
|
|
|
from backend.lib.config import Config
|
|
from django.conf import settings
|
|
from django.contrib import auth
|
|
from django.contrib.auth import authenticate, get_user_model, login, logout
|
|
from django.contrib.auth.models import User
|
|
from django.db import models
|
|
from django.http import JsonResponse
|
|
from django.shortcuts import HttpResponse, redirect, render # render_to_response
|
|
from django.template.loader import render_to_string
|
|
from django.utils.datastructures import MultiValueDictKeyError
|
|
from django.utils.text import slugify
|
|
|
|
from .forms import SignUpForm, UserLoginForm
|
|
from .models import Books, Collections, Favorites, Navigation, User
|
|
|
|
config = Config(Path("../"))
|
|
|
|
|
|
|
|
def index(request, query=None, _set=1, _limit=None, _order='title'):
|
|
"""
|
|
Return template index
|
|
"""
|
|
_payload = payload(request, query, _set, _limit, _order)
|
|
return render(
|
|
request,
|
|
"index.html",
|
|
_payload
|
|
)
|
|
|
|
|
|
def favorites(request, query=None, _set=1, _limit=None, _order='title'):
|
|
"""
|
|
Return template index
|
|
"""
|
|
_payload = payload(request, query, _set, _limit, _order, favorites=True, reset=True)
|
|
return render(
|
|
request,
|
|
"index.html",
|
|
_payload
|
|
)
|
|
|
|
|
|
def collectionspage(request):
|
|
|
|
pass
|
|
|
|
|
|
def signup(request):
|
|
if request.method == 'POST':
|
|
form = SignUpForm(request.POST)
|
|
if form.is_valid():
|
|
form.save()
|
|
username = form.cleaned_data.get('username')
|
|
raw_password = form.cleaned_data.get('password1')
|
|
user = authenticate(username=username, password=raw_password)
|
|
login(request, user)
|
|
return redirect('home')
|
|
else:
|
|
form = SignUpForm()
|
|
return render(request, 'signup.html', {'form': form})
|
|
|
|
|
|
def userlogin(request):
|
|
|
|
if request.method == 'POST':
|
|
username = request.POST['username']
|
|
password = request.POST['password']
|
|
user = authenticate(request, username=username, password=password)
|
|
if user is not None:
|
|
login(request, user)
|
|
user.save()
|
|
return redirect('home')
|
|
form = UserLoginForm()
|
|
return render(request, 'login.html', {'form': form})
|
|
|
|
|
|
def userlogout(request):
|
|
logout(request)
|
|
return redirect('home')
|
|
|
|
|
|
def home(request, query=None, _set=1, _limit=None, _order='title'):
|
|
"""
|
|
Reset Search Queries & Return Home
|
|
"""
|
|
_payload = payload(request, query, _set, _limit, _order, reset=True)
|
|
return render(
|
|
request,
|
|
"index.html",
|
|
_payload
|
|
)
|
|
|
|
|
|
def show_collection(request, query, _set, _limit=None, _order='title', **kwargs):
|
|
try:
|
|
_set = int(_set) + 1
|
|
except Exception:
|
|
_set = 1
|
|
|
|
_set = int(_set) # Get set #
|
|
if _set < 1: _set = 1 # If there is no set data, set = 1
|
|
if _limit is None: _limit = 20 # If we havent set limit limit = 20
|
|
_set_max = int(_set) * _limit # Multiply current set by limit to get upper limits
|
|
_set_min = _set_max - _limit # Subtract limiter to get bottom limit
|
|
_now_showing = "%s-%s"%(_set_min, _set_max) # Set the set count
|
|
if query: # Are we sending a query?
|
|
if query != request.session.get('cached_query'): # Is it different to the last query?
|
|
request.session['cached_query'] = query # Set the session data to track the query
|
|
if request.session['ascending']:
|
|
_r = _results = Collections().generic_search(query) # Get the query, or in reverse below
|
|
else: _results = Collections().generic_search(query).reverse()
|
|
_r, _r_len = \
|
|
_results[_set_min:_set_max],\
|
|
len(_results)
|
|
elif query == request.session.get('cached_query'): # The queries are equal check the direction
|
|
if request.session['ascending']:
|
|
_results = Collections().generic_search(query)
|
|
else: _results = Collections().generic_search(query).reverse()
|
|
_r, _r_len = \
|
|
_results.order_by(_order)[_set_min:_set_max],\
|
|
len(_results)
|
|
else:
|
|
try:
|
|
query = request.session['cached_query'] # Is there a cached query?
|
|
if query == None: raise KeyError
|
|
if request.session['ascending']:
|
|
_results = Collections().generic_search(query)
|
|
else: _results = Collections().generic_search(query).reverse()
|
|
_r, _r_len = \
|
|
_results.order_by(_order)[_set_min:_set_max],\
|
|
len(_results)
|
|
except KeyError:
|
|
if request.session['ascending']:
|
|
_r = book_set(request, _order, _limit, _set, False, **kwargs)
|
|
else: _r = book_set(request, _order, _limit, _set, True, **kwargs)
|
|
_r_len, _search = None, None
|
|
|
|
_bookstats = len(Collections().generic_search(query))
|
|
if (_r_len): _btotal = str(_r_len)
|
|
else: _btotal = str(_bookstats)
|
|
|
|
return render(
|
|
request,
|
|
"index.html",
|
|
{
|
|
"Books": _results,
|
|
"Set": str(_set),
|
|
"Version": config.VERSION,
|
|
# "LeftNavCollections": menu("collections"),
|
|
# "LeftNavMenu0": menu("nav_l_0"),
|
|
"BookStats": _btotal,
|
|
"CollectionStats": Collections.objects.all().count(),
|
|
"CollectionObject": collections_list,
|
|
"NowShowing": _now_showing,
|
|
"PostedSearch": query,
|
|
"SearchLen": _r_len,
|
|
"Order": _order,
|
|
})
|
|
|
|
|
|
def flip_sort(request, bookset=1, query=None, _limit=None, _order='title'):
|
|
"""
|
|
Goto next page in bookset
|
|
"""
|
|
try: _set = int(bookset)
|
|
except Exception: _set = 1
|
|
_payload = payload(request, query, _set, _limit, _order, flip_sort=True)
|
|
return render(
|
|
request,
|
|
"index.html",
|
|
_payload,
|
|
)
|
|
|
|
|
|
def next_page(request, bookset, query=None, _limit=None, _order='title'):
|
|
"""
|
|
Goto next page in bookset
|
|
"""
|
|
try:
|
|
_set = int(bookset) + 1
|
|
except Exception:
|
|
_set = 1
|
|
_payload = payload(request, query, _set, _limit, _order)
|
|
return render(
|
|
request,
|
|
"index.html",
|
|
_payload,
|
|
)
|
|
|
|
|
|
def prev_page(request, bookset, query=None, _limit=None, _order='title'):
|
|
"""
|
|
Goto previous page in bookset
|
|
"""
|
|
_set = int(bookset)
|
|
if _set <= 1:
|
|
_set = 1
|
|
else:
|
|
try:
|
|
_set = int(bookset) - 1
|
|
except Exception:
|
|
_set = 1
|
|
_payload = payload(request, query, _set, _limit, _order)
|
|
return render(
|
|
request,
|
|
"index.html",
|
|
_payload,
|
|
)
|
|
|
|
|
|
def book_set(request, _order, _limit=None, _set=1, _flip=False, **kwargs):
|
|
"""
|
|
Get books results by set #
|
|
"""
|
|
try:
|
|
book_key = []
|
|
if kwargs['favorites'] is True:
|
|
for id in Favorites.objects.all().filter(user=request.user):
|
|
book_key.append(id.book.id)
|
|
BookObject = Books.objects.filter(id__in=(book_key))
|
|
except KeyError: BookObject = Books.objects.all()
|
|
if _limit is None:
|
|
_limit = 20 # TODO default from user choice
|
|
_set_max = int(_set) * _limit
|
|
_set_min = _set_max - _limit
|
|
if _flip:
|
|
books = BookObject.order_by(_order).reverse()[_set_min:_set_max]
|
|
else:
|
|
books = BookObject.order_by(_order)[_set_min:_set_max]
|
|
return mark_favorites(request, books)
|
|
|
|
|
|
def mark_favorites(request, bookset):
|
|
try:
|
|
favorites = Favorites.objects.filter(user=request.user)
|
|
for book in bookset:
|
|
for favorite in favorites:
|
|
if book == favorite.book:
|
|
book.is_favorite = True
|
|
pass
|
|
return bookset
|
|
except Exception as e:
|
|
for book in bookset:
|
|
book.if_favorite = False
|
|
return bookset
|
|
|
|
|
|
def collection(_collection, _set, _limit=None):
|
|
"""
|
|
Get books by collection id
|
|
"""
|
|
_books = []
|
|
books = []
|
|
if _limit is None:
|
|
_limit = 20
|
|
_set_max = int(_set) * _limit
|
|
_set_min = _set_max - _limit
|
|
_collections = Collections.objects.filter(collection=_collection)
|
|
for c in _collections:
|
|
_books.append(c.book_id_id)
|
|
return Books.objects.filter(id__in=_books)
|
|
|
|
|
|
def download(request, pk):
|
|
"""
|
|
Download book by primary key
|
|
"""
|
|
_book = Books.objects.get(pk=pk)
|
|
_fn = hr_name(_book)
|
|
response = HttpResponse(
|
|
open(os.path.abspath(_book.file_name), "rb"), content_type="application/zip"
|
|
)
|
|
response["Content-Disposition"] = "attachment; filename=%s" % _fn
|
|
return response
|
|
|
|
|
|
def favorite(request, pk):
|
|
"""
|
|
Add book to favorites bu primary key
|
|
"""
|
|
try:
|
|
_d = Favorites.objects.filter(user=request.user, book=Books.objects.get(pk=pk))
|
|
except TypeError as e:
|
|
return redirect('login')
|
|
if len(_d) == 1:
|
|
_d.delete()
|
|
return HttpResponse(status=204)
|
|
_f = Favorites(book=Books.objects.get(pk=pk))
|
|
_f.user = request.user
|
|
_f.save()
|
|
return HttpResponse(status=204)
|
|
|
|
|
|
def share(request, pk):
|
|
"""
|
|
Share book by primary key
|
|
"""
|
|
_book = Books.objects.all().filter(pk=pk)[0]
|
|
_fn = hr_name(_book)
|
|
response = HttpResponse(
|
|
open(os.path.abspath(_book.file_name), "rb"), content_type="application/zip"
|
|
)
|
|
response["Content-Disposition"] = "attachment; filename=%s" % _fn
|
|
return response
|
|
|
|
|
|
def info(request, pk):
|
|
"""
|
|
Share book by primary key
|
|
"""
|
|
_book = Books.objects.all().filter(pk=pk)[0]
|
|
_fn = hr_name(_book)
|
|
response = HttpResponse(
|
|
open(os.path.abspath(_book.file_name), "rb"), content_type="application/zip"
|
|
)
|
|
response["Content-Disposition"] = "attachment; filename=%s" % _fn
|
|
return response
|
|
|
|
|
|
def hr_name(book):
|
|
"""
|
|
Nicer file names
|
|
"""
|
|
return "{0}{1}".format(slugify(book.title), os.path.splitext(book.file_name)[1])
|
|
|
|
|
|
def format_list(list_in):
|
|
formated_list, formated_list_key, x = [], [], 0
|
|
for i in list_in:
|
|
if i.id not in formated_list_key:
|
|
if x % 2 == 0:
|
|
c = 0
|
|
else:
|
|
c = 1
|
|
if x <= 10:
|
|
x += 1
|
|
else:
|
|
x = 0
|
|
|
|
|
|
def menu(which, _set=1, parent=None):
|
|
if which == "collections":
|
|
_collections_list = Collections.objects.all()
|
|
_collections, collection_key, x = [], [], 0
|
|
for i in _collections_list:
|
|
if i.collection not in collection_key:
|
|
if x % 2 == 0: c = 0
|
|
else: c = 1
|
|
if x <= 10: x = x + 1
|
|
else: x = 0
|
|
# TODO trim #'s and symbols from front of collection name
|
|
if len(i.collection) > 16:
|
|
collection_string = i.collection[0:16] + " ..."
|
|
else:
|
|
collection_string = i.collection
|
|
|
|
_collections.append(
|
|
{"string": collection_string, "link": i.collection, "class": c}
|
|
)
|
|
collection_key.append(i.collection)
|
|
return _collections
|
|
elif which == "nav_lvl_0":
|
|
navigation_list = Navigation.objects.all()
|
|
return navigation_list
|
|
|
|
|
|
def collections_list():
|
|
collections = Collections.objects.all()
|
|
collection_key = []
|
|
for i in collections:
|
|
if i.collection not in collection_key:
|
|
collection_key.append(i.collection)
|
|
return list(set(collection_key))
|
|
|
|
|
|
def live(request, **kwargs):
|
|
"""
|
|
Respond to live requests. Primarily used as a response object for Ajax calls
|
|
:param GET['hook']: collection_listing, book_details, register
|
|
:param kwargs['pk']: Primary key of requested object
|
|
:return: JsonResponse Object, status response code
|
|
"""
|
|
err_txt = {"err": "There is no responder for your request"}
|
|
try: hook = request.GET['hook']
|
|
except MultiValueDictKeyError as e: return JsonResponse(err_txt, status=404)
|
|
|
|
if hook == "collection_listing":
|
|
collections = collections_list()
|
|
return JsonResponse({"data": collections}, status=200)
|
|
elif hook == "book_details":
|
|
return JsonResponse({"data": Books.objects.get(pk=kwargs['pk'])}, status=200)
|
|
elif hook == "register":
|
|
html = render_to_string('signup.html', {'form': SignUpForm}, request)
|
|
html += render_to_string('login.html', {'form': UserLoginForm}, request)
|
|
return JsonResponse({"data": html})
|
|
else: return JsonResponse(err_txt, status=404)
|
|
|
|
return JsonResponse({"data": "Response sent"}, status=200)
|
|
|
|
|
|
def payload(request, query, _set, _limit, _order, **kwargs):
|
|
"""
|
|
Return formatted data to template
|
|
: notes : This is the least pythonic function I have ever written, but its
|
|
still beautiful
|
|
"""
|
|
try: request.session['ascending']
|
|
except KeyError: request.session['ascending'] = True
|
|
try: # Are we fliping the sort?
|
|
if kwargs['flip_sort']:
|
|
request.session['ascending'] = not request.session['ascending']
|
|
except KeyError: pass
|
|
try: # Are we resetting the session?
|
|
if kwargs['reset']:
|
|
request.session['cached_query'] = query
|
|
if _set < 1: _set = 1
|
|
if _limit is None: _limit = 20
|
|
_set_max = int(_set) * _limit
|
|
_set_min = _set_max - _limit
|
|
_now_showing = "%s-%s"%(_set_min, _set_max)
|
|
if request.session['ascending']:
|
|
_r = book_set(request, _order, _limit, _set, False, **kwargs)
|
|
else: _r = book_set(request, _order, _limit, _set, True, **kwargs)
|
|
_r_len, _search = None, None
|
|
except KeyError:
|
|
_set = int(_set) # Get set #
|
|
if _set < 1: _set = 1 # If there is no set data, set = 1
|
|
if _limit is None: _limit = 20 # If we havent set limit limit = 20
|
|
_set_max = int(_set) * _limit # Multiply current set by limit to get upper limits
|
|
_set_min = _set_max - _limit # Subtract limiter to get bottom limit
|
|
_now_showing = "%s-%s"%(_set_min, _set_max) # Set the set count
|
|
if query: # Are we sending a query?
|
|
if query != request.session.get('cached_query'): # Is it differnt to the last query?
|
|
request.session['cached_query'] = query # Set the session data to track the query
|
|
if request.session['ascending']:
|
|
_results = Books().generic_search(query) # Get the query, or in reverse below
|
|
else: _results = Books().generic_search(query).reverse()
|
|
_r, _r_len = \
|
|
_results[_set_min:_set_max],\
|
|
_results.count()
|
|
elif query == request.session.get('cached_query'): # The queries are equal check the direction
|
|
if request.session['ascending']:
|
|
_results = Books().generic_search(query)
|
|
else: _results = Books().generic_search(query).reverse()
|
|
_r, _r_len = \
|
|
_results.order_by(_order)[_set_min:_set_max],\
|
|
_results.count()
|
|
else: # No new query was passed
|
|
try:
|
|
query = request.session['cached_query'] # Is there a cached query?
|
|
if query == None: raise KeyError # No cached query exists jump to KeyError
|
|
if request.session['ascending']:
|
|
_results = Books().generic_search(query)
|
|
else: _results = Books().generic_search(query).reverse()
|
|
_r, _r_len = \
|
|
_results.order_by(_order)[_set_min:_set_max],\
|
|
_results.count()
|
|
except KeyError:
|
|
if request.session['ascending']:
|
|
_r = book_set(request, _order, _limit, _set, False, **kwargs)
|
|
else: _r = book_set(request, _order, _limit, _set, True, **kwargs)
|
|
_r_len, _search = None, None
|
|
|
|
_bookstats = Books.objects.all().count()
|
|
if (_r_len): _btotal = str(_r_len)
|
|
else: _btotal = str(_bookstats)
|
|
# Format the payload and return it to the view
|
|
return {
|
|
"Books": _r,
|
|
"Set": str(_set),
|
|
"Version": config.VERSION,
|
|
# "LeftNavCollections": menu("collections"),
|
|
# "LeftNavMenu0": menu("nav_l_0"),
|
|
"BookStats": _btotal,
|
|
"CollectionStats": Collections.objects.all().count(),
|
|
"CollectionObject": collections_list,
|
|
"NowShowing": _now_showing,
|
|
"PostedSearch": query,
|
|
"SearchLen": _r_len,
|
|
"Order": _order,
|
|
}
|