Files
pyShelf/src/interface/views.py
2020-07-31 02:27:07 -04:00

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,
}