|
|
|
@ -29,7 +29,7 @@ import copy
|
|
|
|
|
from functools import wraps
|
|
|
|
|
|
|
|
|
|
from babel.dates import format_date
|
|
|
|
|
from babel import Locale as LC
|
|
|
|
|
from babel import Locale
|
|
|
|
|
from flask import Blueprint, jsonify
|
|
|
|
|
from flask import request, redirect, send_from_directory, make_response, flash, abort, url_for
|
|
|
|
|
from flask import session as flask_session
|
|
|
|
@ -60,7 +60,6 @@ from .kobo_sync_status import remove_synced_book
|
|
|
|
|
from .render_template import render_title_template
|
|
|
|
|
from .kobo_sync_status import change_archived_books
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
feature_support = {
|
|
|
|
|
'ldap': bool(services.ldap),
|
|
|
|
|
'goodreads': bool(services.goodreads_support),
|
|
|
|
@ -69,10 +68,12 @@ feature_support = {
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
from .oauth_bb import oauth_check, register_user_with_oauth, logout_oauth_user, get_oauth_status
|
|
|
|
|
|
|
|
|
|
feature_support['oauth'] = True
|
|
|
|
|
except ImportError:
|
|
|
|
|
feature_support['oauth'] = False
|
|
|
|
|
oauth_check = {}
|
|
|
|
|
register_user_with_oauth = logout_oauth_user = get_oauth_status = None
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
from natsort import natsorted as sort
|
|
|
|
@ -82,8 +83,11 @@ except ImportError:
|
|
|
|
|
|
|
|
|
|
@app.after_request
|
|
|
|
|
def add_security_headers(resp):
|
|
|
|
|
resp.headers['Content-Security-Policy'] = "default-src 'self'" + ''.join([' '+host for host in config.config_trustedhosts.strip().split(',')]) + " 'unsafe-inline' 'unsafe-eval'; font-src 'self' data:; img-src 'self' data:"
|
|
|
|
|
if request.endpoint == "editbook.edit_book" or config.config_use_google_drive:
|
|
|
|
|
csp = "default-src 'self'"
|
|
|
|
|
csp += ''.join([' ' + host for host in config.config_trustedhosts.strip().split(',')])
|
|
|
|
|
csp += " 'unsafe-inline' 'unsafe-eval'; font-src 'self' data:; img-src 'self' data:"
|
|
|
|
|
resp.headers['Content-Security-Policy'] = csp
|
|
|
|
|
if request.endpoint == "edit-book.edit_book" or config.config_use_google_drive:
|
|
|
|
|
resp.headers['Content-Security-Policy'] += " *"
|
|
|
|
|
elif request.endpoint == "web.read_book":
|
|
|
|
|
resp.headers['Content-Security-Policy'] += " blob:;style-src-elem 'self' blob: 'unsafe-inline';"
|
|
|
|
@ -93,6 +97,7 @@ def add_security_headers(resp):
|
|
|
|
|
resp.headers['Strict-Transport-Security'] = 'max-age=31536000;'
|
|
|
|
|
return resp
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
web = Blueprint('web', __name__)
|
|
|
|
|
log = logger.create()
|
|
|
|
|
|
|
|
|
@ -119,6 +124,7 @@ def viewer_required(f):
|
|
|
|
|
|
|
|
|
|
return inner
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# ################################### data provider functions #########################################################
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -140,11 +146,11 @@ def set_bookmark(book_id, book_format):
|
|
|
|
|
ub.session_commit()
|
|
|
|
|
return "", 204
|
|
|
|
|
|
|
|
|
|
lbookmark = ub.Bookmark(user_id=current_user.id,
|
|
|
|
|
book_id=book_id,
|
|
|
|
|
format=book_format,
|
|
|
|
|
bookmark_key=bookmark_key)
|
|
|
|
|
ub.session.merge(lbookmark)
|
|
|
|
|
l_bookmark = ub.Bookmark(user_id=current_user.id,
|
|
|
|
|
book_id=book_id,
|
|
|
|
|
format=book_format,
|
|
|
|
|
bookmark_key=bookmark_key)
|
|
|
|
|
ub.session.merge(l_bookmark)
|
|
|
|
|
ub.session_commit("Bookmark for user {} in book {} created".format(current_user.id, book_id))
|
|
|
|
|
return "", 201
|
|
|
|
|
|
|
|
|
@ -162,7 +168,7 @@ def toggle_read(book_id):
|
|
|
|
|
@web.route("/ajax/togglearchived/<int:book_id>", methods=['POST'])
|
|
|
|
|
@login_required
|
|
|
|
|
def toggle_archived(book_id):
|
|
|
|
|
is_archived = change_archived_books(book_id, message="Book {} archivebit toggled".format(book_id))
|
|
|
|
|
is_archived = change_archived_books(book_id, message="Book {} archive bit toggled".format(book_id))
|
|
|
|
|
if is_archived:
|
|
|
|
|
remove_synced_book(book_id)
|
|
|
|
|
return ""
|
|
|
|
@ -230,6 +236,7 @@ def get_comic_book(book_id, book_format, page):
|
|
|
|
|
return "", 204
|
|
|
|
|
'''
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# ################################### Typeahead ##################################################################
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -297,6 +304,12 @@ def get_matching_tags():
|
|
|
|
|
return json_dumps
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def generate_char_list(data_colum, db_link):
|
|
|
|
|
return (calibre_db.session.query(func.upper(func.substr(data_colum, 1, 1)).label('char'))
|
|
|
|
|
.join(db_link).join(db.Books).filter(calibre_db.common_filters())
|
|
|
|
|
.group_by(func.upper(func.substr(data_colum, 1, 1))).all())
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_sort_function(sort_param, data):
|
|
|
|
|
order = [db.Books.timestamp.desc()]
|
|
|
|
|
if sort_param == 'stored':
|
|
|
|
@ -373,7 +386,7 @@ def render_books_list(data, sort_param, book_id, page):
|
|
|
|
|
else:
|
|
|
|
|
website = data or "newest"
|
|
|
|
|
entries, random, pagination = calibre_db.fill_indexpage(page, 0, db.Books, True, order[0],
|
|
|
|
|
False, 0,
|
|
|
|
|
False, 0,
|
|
|
|
|
db.books_series_link,
|
|
|
|
|
db.Books.id == db.books_series_link.c.book,
|
|
|
|
|
db.Series)
|
|
|
|
@ -407,12 +420,13 @@ def render_discover_books(page, book_id):
|
|
|
|
|
else:
|
|
|
|
|
abort(404)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def render_hot_books(page, order):
|
|
|
|
|
if current_user.check_visibility(constants.SIDEBAR_HOT):
|
|
|
|
|
if order[1] not in ['hotasc', 'hotdesc']:
|
|
|
|
|
# Unary expression comparsion only working (for this expression) in sqlalchemy 1.4+
|
|
|
|
|
#if not (order[0][0].compare(func.count(ub.Downloads.book_id).desc()) or
|
|
|
|
|
# order[0][0].compare(func.count(ub.Downloads.book_id).asc())):
|
|
|
|
|
# Unary expression comparsion only working (for this expression) in sqlalchemy 1.4+
|
|
|
|
|
# if not (order[0][0].compare(func.count(ub.Downloads.book_id).desc()) or
|
|
|
|
|
# order[0][0].compare(func.count(ub.Downloads.book_id).asc())):
|
|
|
|
|
order = [func.count(ub.Downloads.book_id).desc()], 'hotdesc'
|
|
|
|
|
if current_user.show_detail_random():
|
|
|
|
|
random = calibre_db.session.query(db.Books).filter(calibre_db.common_filters()) \
|
|
|
|
@ -420,19 +434,19 @@ def render_hot_books(page, order):
|
|
|
|
|
else:
|
|
|
|
|
random = false()
|
|
|
|
|
off = int(int(config.config_books_per_page) * (page - 1))
|
|
|
|
|
all_books = ub.session.query(ub.Downloads, func.count(ub.Downloads.book_id))\
|
|
|
|
|
all_books = ub.session.query(ub.Downloads, func.count(ub.Downloads.book_id)) \
|
|
|
|
|
.order_by(*order[0]).group_by(ub.Downloads.book_id)
|
|
|
|
|
hot_books = all_books.offset(off).limit(config.config_books_per_page)
|
|
|
|
|
entries = list()
|
|
|
|
|
for book in hot_books:
|
|
|
|
|
downloadBook = calibre_db.session.query(db.Books).filter(calibre_db.common_filters()).filter(
|
|
|
|
|
download_book = calibre_db.session.query(db.Books).filter(calibre_db.common_filters()).filter(
|
|
|
|
|
db.Books.id == book.Downloads.book_id).first()
|
|
|
|
|
if downloadBook:
|
|
|
|
|
entries.append(downloadBook)
|
|
|
|
|
if download_book:
|
|
|
|
|
entries.append(download_book)
|
|
|
|
|
else:
|
|
|
|
|
ub.delete_download(book.Downloads.book_id)
|
|
|
|
|
numBooks = entries.__len__()
|
|
|
|
|
pagination = Pagination(page, config.config_books_per_page, numBooks)
|
|
|
|
|
num_books = entries.__len__()
|
|
|
|
|
pagination = Pagination(page, config.config_books_per_page, num_books)
|
|
|
|
|
return render_title_template('index.html', random=random, entries=entries, pagination=pagination,
|
|
|
|
|
title=_(u"Hot Books (Most Downloaded)"), page="hot", order=order[1])
|
|
|
|
|
else:
|
|
|
|
@ -462,8 +476,8 @@ def render_downloaded_books(page, order, user_id):
|
|
|
|
|
db.Series,
|
|
|
|
|
ub.Downloads, db.Books.id == ub.Downloads.book_id)
|
|
|
|
|
for book in entries:
|
|
|
|
|
if not calibre_db.session.query(db.Books).filter(calibre_db.common_filters()) \
|
|
|
|
|
.filter(db.Books.id == book.id).first():
|
|
|
|
|
if not calibre_db.session.query(db.Books).\
|
|
|
|
|
filter(calibre_db.common_filters()).filter(db.Books.id == book.id).first():
|
|
|
|
|
ub.delete_download(book.id)
|
|
|
|
|
user = ub.session.query(ub.User).filter(ub.User.id == user_id).first()
|
|
|
|
|
return render_title_template('index.html',
|
|
|
|
@ -471,7 +485,7 @@ def render_downloaded_books(page, order, user_id):
|
|
|
|
|
entries=entries,
|
|
|
|
|
pagination=pagination,
|
|
|
|
|
id=user_id,
|
|
|
|
|
title=_(u"Downloaded books by %(user)s",user=user.name),
|
|
|
|
|
title=_(u"Downloaded books by %(user)s", user=user.name),
|
|
|
|
|
page="download",
|
|
|
|
|
order=order[1])
|
|
|
|
|
else:
|
|
|
|
@ -639,29 +653,27 @@ def render_read_books(page, are_read, as_xml=False, order=None):
|
|
|
|
|
column=config.config_read_column),
|
|
|
|
|
category="error")
|
|
|
|
|
return redirect(url_for("web.index"))
|
|
|
|
|
return [] # ToDo: Handle error Case for opds
|
|
|
|
|
return [] # ToDo: Handle error Case for opds
|
|
|
|
|
|
|
|
|
|
if as_xml:
|
|
|
|
|
return entries, pagination
|
|
|
|
|
else:
|
|
|
|
|
if are_read:
|
|
|
|
|
name = _(u'Read Books') + ' (' + str(pagination.total_count) + ')'
|
|
|
|
|
pagename = "read"
|
|
|
|
|
page_name = "read"
|
|
|
|
|
else:
|
|
|
|
|
name = _(u'Unread Books') + ' (' + str(pagination.total_count) + ')'
|
|
|
|
|
pagename = "unread"
|
|
|
|
|
page_name = "unread"
|
|
|
|
|
return render_title_template('index.html', random=random, entries=entries, pagination=pagination,
|
|
|
|
|
title=name, page=pagename, order=order[1])
|
|
|
|
|
title=name, page=page_name, order=order[1])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def render_archived_books(page, sort_param):
|
|
|
|
|
order = sort_param[0] or []
|
|
|
|
|
archived_books = (
|
|
|
|
|
ub.session.query(ub.ArchivedBook)
|
|
|
|
|
.filter(ub.ArchivedBook.user_id == int(current_user.id))
|
|
|
|
|
.filter(ub.ArchivedBook.is_archived == True)
|
|
|
|
|
.all()
|
|
|
|
|
)
|
|
|
|
|
archived_books = (ub.session.query(ub.ArchivedBook)
|
|
|
|
|
.filter(ub.ArchivedBook.user_id == int(current_user.id))
|
|
|
|
|
.filter(ub.ArchivedBook.is_archived == True)
|
|
|
|
|
.all())
|
|
|
|
|
archived_book_ids = [archived_book.book_id for archived_book in archived_books]
|
|
|
|
|
|
|
|
|
|
archived_filter = db.Books.id.in_(archived_book_ids)
|
|
|
|
@ -674,40 +686,40 @@ def render_archived_books(page, sort_param):
|
|
|
|
|
False, 0)
|
|
|
|
|
|
|
|
|
|
name = _(u'Archived Books') + ' (' + str(len(archived_book_ids)) + ')'
|
|
|
|
|
pagename = "archived"
|
|
|
|
|
page_name = "archived"
|
|
|
|
|
return render_title_template('index.html', random=random, entries=entries, pagination=pagination,
|
|
|
|
|
title=name, page=pagename, order=sort_param[1])
|
|
|
|
|
title=name, page=page_name, order=sort_param[1])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def render_prepare_search_form(cc):
|
|
|
|
|
# prepare data for search-form
|
|
|
|
|
tags = calibre_db.session.query(db.Tags)\
|
|
|
|
|
.join(db.books_tags_link)\
|
|
|
|
|
.join(db.Books)\
|
|
|
|
|
tags = calibre_db.session.query(db.Tags) \
|
|
|
|
|
.join(db.books_tags_link) \
|
|
|
|
|
.join(db.Books) \
|
|
|
|
|
.filter(calibre_db.common_filters()) \
|
|
|
|
|
.group_by(text('books_tags_link.tag'))\
|
|
|
|
|
.group_by(text('books_tags_link.tag')) \
|
|
|
|
|
.order_by(db.Tags.name).all()
|
|
|
|
|
series = calibre_db.session.query(db.Series)\
|
|
|
|
|
.join(db.books_series_link)\
|
|
|
|
|
.join(db.Books)\
|
|
|
|
|
series = calibre_db.session.query(db.Series) \
|
|
|
|
|
.join(db.books_series_link) \
|
|
|
|
|
.join(db.Books) \
|
|
|
|
|
.filter(calibre_db.common_filters()) \
|
|
|
|
|
.group_by(text('books_series_link.series'))\
|
|
|
|
|
.order_by(db.Series.name)\
|
|
|
|
|
.group_by(text('books_series_link.series')) \
|
|
|
|
|
.order_by(db.Series.name) \
|
|
|
|
|
.filter(calibre_db.common_filters()).all()
|
|
|
|
|
shelves = ub.session.query(ub.Shelf)\
|
|
|
|
|
.filter(or_(ub.Shelf.is_public == 1, ub.Shelf.user_id == int(current_user.id)))\
|
|
|
|
|
shelves = ub.session.query(ub.Shelf) \
|
|
|
|
|
.filter(or_(ub.Shelf.is_public == 1, ub.Shelf.user_id == int(current_user.id))) \
|
|
|
|
|
.order_by(ub.Shelf.name).all()
|
|
|
|
|
extensions = calibre_db.session.query(db.Data)\
|
|
|
|
|
.join(db.Books)\
|
|
|
|
|
extensions = calibre_db.session.query(db.Data) \
|
|
|
|
|
.join(db.Books) \
|
|
|
|
|
.filter(calibre_db.common_filters()) \
|
|
|
|
|
.group_by(db.Data.format)\
|
|
|
|
|
.group_by(db.Data.format) \
|
|
|
|
|
.order_by(db.Data.format).all()
|
|
|
|
|
if current_user.filter_language() == u"all":
|
|
|
|
|
languages = calibre_db.speaking_language()
|
|
|
|
|
else:
|
|
|
|
|
languages = None
|
|
|
|
|
return render_title_template('search_form.html', tags=tags, languages=languages, extensions=extensions,
|
|
|
|
|
series=series,shelves=shelves, title=_(u"Advanced Search"), cc=cc, page="advsearch")
|
|
|
|
|
series=series, shelves=shelves, title=_(u"Advanced Search"), cc=cc, page="advsearch")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def render_search_results(term, offset=None, order=None, limit=None):
|
|
|
|
@ -716,7 +728,6 @@ def render_search_results(term, offset=None, order=None, limit=None):
|
|
|
|
|
offset,
|
|
|
|
|
order,
|
|
|
|
|
limit,
|
|
|
|
|
False,
|
|
|
|
|
config.config_read_column,
|
|
|
|
|
*join)
|
|
|
|
|
return render_title_template('search.html',
|
|
|
|
@ -759,12 +770,13 @@ def books_table():
|
|
|
|
|
return render_title_template('book_table.html', title=_(u"Books List"), cc=cc, page="book_table",
|
|
|
|
|
visiblility=visibility)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@web.route("/ajax/listbooks")
|
|
|
|
|
@login_required
|
|
|
|
|
def list_books():
|
|
|
|
|
off = int(request.args.get("offset") or 0)
|
|
|
|
|
limit = int(request.args.get("limit") or config.config_books_per_page)
|
|
|
|
|
search = request.args.get("search")
|
|
|
|
|
search_param = request.args.get("search")
|
|
|
|
|
sort_param = request.args.get("sort", "id")
|
|
|
|
|
order = request.args.get("order", "").lower()
|
|
|
|
|
state = None
|
|
|
|
@ -784,8 +796,8 @@ def list_books():
|
|
|
|
|
elif sort_param == "authors":
|
|
|
|
|
order = [db.Authors.name.asc(), db.Series.name, db.Books.series_index] if order == "asc" \
|
|
|
|
|
else [db.Authors.name.desc(), db.Series.name.desc(), db.Books.series_index.desc()]
|
|
|
|
|
join = db.books_authors_link, db.Books.id == db.books_authors_link.c.book, db.Authors, \
|
|
|
|
|
db.books_series_link, db.Books.id == db.books_series_link.c.book, db.Series
|
|
|
|
|
join = db.books_authors_link, db.Books.id == db.books_authors_link.c.book, db.Authors, db.books_series_link, \
|
|
|
|
|
db.Books.id == db.books_series_link.c.book, db.Series
|
|
|
|
|
elif sort_param == "languages":
|
|
|
|
|
order = [db.Languages.lang_code.asc()] if order == "asc" else [db.Languages.lang_code.desc()]
|
|
|
|
|
join = db.books_languages_link, db.Books.id == db.books_languages_link.c.book, db.Languages
|
|
|
|
@ -794,10 +806,11 @@ def list_books():
|
|
|
|
|
elif not state:
|
|
|
|
|
order = [db.Books.timestamp.desc()]
|
|
|
|
|
|
|
|
|
|
total_count = filtered_count = calibre_db.session.query(db.Books).filter(calibre_db.common_filters(allow_show_archived=True)).count()
|
|
|
|
|
total_count = filtered_count = calibre_db.session.query(db.Books).filter(
|
|
|
|
|
calibre_db.common_filters(allow_show_archived=True)).count()
|
|
|
|
|
if state is not None:
|
|
|
|
|
if search:
|
|
|
|
|
books = calibre_db.search_query(search, config.config_read_column).all()
|
|
|
|
|
if search_param:
|
|
|
|
|
books = calibre_db.search_query(search_param, config.config_read_column).all()
|
|
|
|
|
filtered_count = len(books)
|
|
|
|
|
else:
|
|
|
|
|
if not config.config_read_column:
|
|
|
|
@ -818,15 +831,14 @@ def list_books():
|
|
|
|
|
# Skip linking read column and return None instead of read status
|
|
|
|
|
books = calibre_db.session.query(db.Books, None, ub.ArchivedBook.is_archived)
|
|
|
|
|
books = (books.outerjoin(ub.ArchivedBook, and_(db.Books.id == ub.ArchivedBook.book_id,
|
|
|
|
|
int(current_user.id) == ub.ArchivedBook.user_id))
|
|
|
|
|
int(current_user.id) == ub.ArchivedBook.user_id))
|
|
|
|
|
.filter(calibre_db.common_filters(allow_show_archived=True)).all())
|
|
|
|
|
entries = calibre_db.get_checkbox_sorted(books, state, off, limit, order, True)
|
|
|
|
|
elif search:
|
|
|
|
|
entries, filtered_count, __ = calibre_db.get_search_results(search,
|
|
|
|
|
elif search_param:
|
|
|
|
|
entries, filtered_count, __ = calibre_db.get_search_results(search_param,
|
|
|
|
|
off,
|
|
|
|
|
[order,''],
|
|
|
|
|
[order, ''],
|
|
|
|
|
limit,
|
|
|
|
|
True,
|
|
|
|
|
config.config_read_column,
|
|
|
|
|
*join)
|
|
|
|
|
else:
|
|
|
|
@ -845,9 +857,9 @@ def list_books():
|
|
|
|
|
val = entry[0]
|
|
|
|
|
val.read_status = entry[1] == ub.ReadBook.STATUS_FINISHED
|
|
|
|
|
val.is_archived = entry[2] is True
|
|
|
|
|
for index in range(0, len(val.languages)):
|
|
|
|
|
val.languages[index].language_name = isoLanguages.get_language_name(get_locale(), val.languages[
|
|
|
|
|
index].lang_code)
|
|
|
|
|
for lang_index in range(0, len(val.languages)):
|
|
|
|
|
val.languages[lang_index].language_name = isoLanguages.get_language_name(get_locale(), val.languages[
|
|
|
|
|
lang_index].lang_code)
|
|
|
|
|
result.append(val)
|
|
|
|
|
|
|
|
|
|
table_entries = {'totalNotFiltered': total_count, 'total': filtered_count, "rows": result}
|
|
|
|
@ -857,6 +869,7 @@ def list_books():
|
|
|
|
|
response.headers["Content-Type"] = "application/json; charset=utf-8"
|
|
|
|
|
return response
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@web.route("/ajax/table_settings", methods=['POST'])
|
|
|
|
|
@login_required
|
|
|
|
|
def update_table_settings():
|
|
|
|
@ -886,19 +899,18 @@ def author_list():
|
|
|
|
|
entries = calibre_db.session.query(db.Authors, func.count('books_authors_link.book').label('count')) \
|
|
|
|
|
.join(db.books_authors_link).join(db.Books).filter(calibre_db.common_filters()) \
|
|
|
|
|
.group_by(text('books_authors_link.author')).order_by(order).all()
|
|
|
|
|
charlist = calibre_db.session.query(func.upper(func.substr(db.Authors.sort, 1, 1)).label('char')) \
|
|
|
|
|
.join(db.books_authors_link).join(db.Books).filter(calibre_db.common_filters()) \
|
|
|
|
|
.group_by(func.upper(func.substr(db.Authors.sort, 1, 1))).all()
|
|
|
|
|
char_list = generate_char_list(db.Authors.sort, db.books_authors_link)
|
|
|
|
|
# If not creating a copy, readonly databases can not display authornames with "|" in it as changing the name
|
|
|
|
|
# starts a change session
|
|
|
|
|
autor_copy = copy.deepcopy(entries)
|
|
|
|
|
for entry in autor_copy:
|
|
|
|
|
author_copy = copy.deepcopy(entries)
|
|
|
|
|
for entry in author_copy:
|
|
|
|
|
entry.Authors.name = entry.Authors.name.replace('|', ',')
|
|
|
|
|
return render_title_template('list.html', entries=autor_copy, folder='web.books_list', charlist=charlist,
|
|
|
|
|
return render_title_template('list.html', entries=author_copy, folder='web.books_list', charlist=char_list,
|
|
|
|
|
title=u"Authors", page="authorlist", data='author', order=order_no)
|
|
|
|
|
else:
|
|
|
|
|
abort(404)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@web.route("/downloadlist")
|
|
|
|
|
@login_required_if_no_ano
|
|
|
|
|
def download_list():
|
|
|
|
@ -909,12 +921,12 @@ def download_list():
|
|
|
|
|
order = ub.User.name.asc()
|
|
|
|
|
order_no = 1
|
|
|
|
|
if current_user.check_visibility(constants.SIDEBAR_DOWNLOAD) and current_user.role_admin():
|
|
|
|
|
entries = ub.session.query(ub.User, func.count(ub.Downloads.book_id).label('count'))\
|
|
|
|
|
entries = ub.session.query(ub.User, func.count(ub.Downloads.book_id).label('count')) \
|
|
|
|
|
.join(ub.Downloads).group_by(ub.Downloads.user_id).order_by(order).all()
|
|
|
|
|
charlist = ub.session.query(func.upper(func.substr(ub.User.name, 1, 1)).label('char')) \
|
|
|
|
|
char_list = ub.session.query(func.upper(func.substr(ub.User.name, 1, 1)).label('char')) \
|
|
|
|
|
.filter(ub.User.role.op('&')(constants.ROLE_ANONYMOUS) != constants.ROLE_ANONYMOUS) \
|
|
|
|
|
.group_by(func.upper(func.substr(ub.User.name, 1, 1))).all()
|
|
|
|
|
return render_title_template('list.html', entries=entries, folder='web.books_list', charlist=charlist,
|
|
|
|
|
return render_title_template('list.html', entries=entries, folder='web.books_list', charlist=char_list,
|
|
|
|
|
title=_(u"Downloads"), page="downloadlist", data="download", order=order_no)
|
|
|
|
|
else:
|
|
|
|
|
abort(404)
|
|
|
|
@ -933,10 +945,8 @@ def publisher_list():
|
|
|
|
|
entries = calibre_db.session.query(db.Publishers, func.count('books_publishers_link.book').label('count')) \
|
|
|
|
|
.join(db.books_publishers_link).join(db.Books).filter(calibre_db.common_filters()) \
|
|
|
|
|
.group_by(text('books_publishers_link.publisher')).order_by(order).all()
|
|
|
|
|
charlist = calibre_db.session.query(func.upper(func.substr(db.Publishers.name, 1, 1)).label('char')) \
|
|
|
|
|
.join(db.books_publishers_link).join(db.Books).filter(calibre_db.common_filters()) \
|
|
|
|
|
.group_by(func.upper(func.substr(db.Publishers.name, 1, 1))).all()
|
|
|
|
|
return render_title_template('list.html', entries=entries, folder='web.books_list', charlist=charlist,
|
|
|
|
|
char_list = generate_char_list(db.Publishers.name, db.books_publishers_link)
|
|
|
|
|
return render_title_template('list.html', entries=entries, folder='web.books_list', charlist=char_list,
|
|
|
|
|
title=_(u"Publishers"), page="publisherlist", data="publisher", order=order_no)
|
|
|
|
|
else:
|
|
|
|
|
abort(404)
|
|
|
|
@ -952,25 +962,19 @@ def series_list():
|
|
|
|
|
else:
|
|
|
|
|
order = db.Series.sort.asc()
|
|
|
|
|
order_no = 1
|
|
|
|
|
char_list = generate_char_list(db.Series.sort, db.books_series_link)
|
|
|
|
|
if current_user.get_view_property('series', 'series_view') == 'list':
|
|
|
|
|
entries = calibre_db.session.query(db.Series, func.count('books_series_link.book').label('count')) \
|
|
|
|
|
.join(db.books_series_link).join(db.Books).filter(calibre_db.common_filters()) \
|
|
|
|
|
.group_by(text('books_series_link.series')).order_by(order).all()
|
|
|
|
|
charlist = calibre_db.session.query(func.upper(func.substr(db.Series.sort, 1, 1)).label('char')) \
|
|
|
|
|
.join(db.books_series_link).join(db.Books).filter(calibre_db.common_filters()) \
|
|
|
|
|
.group_by(func.upper(func.substr(db.Series.sort, 1, 1))).all()
|
|
|
|
|
return render_title_template('list.html', entries=entries, folder='web.books_list', charlist=charlist,
|
|
|
|
|
return render_title_template('list.html', entries=entries, folder='web.books_list', charlist=char_list,
|
|
|
|
|
title=_(u"Series"), page="serieslist", data="series", order=order_no)
|
|
|
|
|
else:
|
|
|
|
|
entries = calibre_db.session.query(db.Books, func.count('books_series_link').label('count'),
|
|
|
|
|
func.max(db.Books.series_index), db.Books.id) \
|
|
|
|
|
.join(db.books_series_link).join(db.Series).filter(calibre_db.common_filters())\
|
|
|
|
|
.join(db.books_series_link).join(db.Series).filter(calibre_db.common_filters()) \
|
|
|
|
|
.group_by(text('books_series_link.series')).order_by(order).all()
|
|
|
|
|
charlist = calibre_db.session.query(func.upper(func.substr(db.Series.sort, 1, 1)).label('char')) \
|
|
|
|
|
.join(db.books_series_link).join(db.Books).filter(calibre_db.common_filters()) \
|
|
|
|
|
.group_by(func.upper(func.substr(db.Series.sort, 1, 1))).all()
|
|
|
|
|
|
|
|
|
|
return render_title_template('grid.html', entries=entries, folder='web.books_list', charlist=charlist,
|
|
|
|
|
return render_title_template('grid.html', entries=entries, folder='web.books_list', charlist=char_list,
|
|
|
|
|
title=_(u"Series"), page="serieslist", data="series", bodyClass="grid-view",
|
|
|
|
|
order=order_no)
|
|
|
|
|
else:
|
|
|
|
@ -988,7 +992,7 @@ def ratings_list():
|
|
|
|
|
order = db.Ratings.rating.asc()
|
|
|
|
|
order_no = 1
|
|
|
|
|
entries = calibre_db.session.query(db.Ratings, func.count('books_ratings_link.book').label('count'),
|
|
|
|
|
(db.Ratings.rating / 2).label('name')) \
|
|
|
|
|
(db.Ratings.rating / 2).label('name')) \
|
|
|
|
|
.join(db.books_ratings_link).join(db.Books).filter(calibre_db.common_filters()) \
|
|
|
|
|
.group_by(text('books_ratings_link.rating')).order_by(order).all()
|
|
|
|
|
return render_title_template('list.html', entries=entries, folder='web.books_list', charlist=list(),
|
|
|
|
@ -1023,14 +1027,14 @@ def formats_list():
|
|
|
|
|
def language_overview():
|
|
|
|
|
if current_user.check_visibility(constants.SIDEBAR_LANGUAGE) and current_user.filter_language() == u"all":
|
|
|
|
|
order_no = 0 if current_user.get_view_property('language', 'dir') == 'desc' else 1
|
|
|
|
|
charlist = list()
|
|
|
|
|
char_list = list()
|
|
|
|
|
languages = calibre_db.speaking_language(reverse_order=not order_no, with_count=True)
|
|
|
|
|
for lang in languages:
|
|
|
|
|
upper_lang = lang[0].name[0].upper()
|
|
|
|
|
if upper_lang not in charlist:
|
|
|
|
|
charlist.append(upper_lang)
|
|
|
|
|
if upper_lang not in char_list:
|
|
|
|
|
char_list.append(upper_lang)
|
|
|
|
|
return render_title_template('languages.html', languages=languages,
|
|
|
|
|
charlist=charlist, title=_(u"Languages"), page="langlist",
|
|
|
|
|
charlist=char_list, title=_(u"Languages"), page="langlist",
|
|
|
|
|
data="language", order=order_no)
|
|
|
|
|
else:
|
|
|
|
|
abort(404)
|
|
|
|
@ -1049,10 +1053,8 @@ def category_list():
|
|
|
|
|
entries = calibre_db.session.query(db.Tags, func.count('books_tags_link.book').label('count')) \
|
|
|
|
|
.join(db.books_tags_link).join(db.Books).order_by(order).filter(calibre_db.common_filters()) \
|
|
|
|
|
.group_by(text('books_tags_link.tag')).all()
|
|
|
|
|
charlist = calibre_db.session.query(func.upper(func.substr(db.Tags.name, 1, 1)).label('char')) \
|
|
|
|
|
.join(db.books_tags_link).join(db.Books).filter(calibre_db.common_filters()) \
|
|
|
|
|
.group_by(func.upper(func.substr(db.Tags.name, 1, 1))).all()
|
|
|
|
|
return render_title_template('list.html', entries=entries, folder='web.books_list', charlist=charlist,
|
|
|
|
|
char_list = generate_char_list(db.Tags.name, db.books_tags_link)
|
|
|
|
|
return render_title_template('list.html', entries=entries, folder='web.books_list', charlist=char_list,
|
|
|
|
|
title=_(u"Categories"), page="catlist", data="category", order=order_no)
|
|
|
|
|
else:
|
|
|
|
|
abort(404)
|
|
|
|
@ -1176,7 +1178,15 @@ def adv_search_read_status(q, read_status):
|
|
|
|
|
return q
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def adv_search_extension(q, include_extension_inputs, exclude_extension_inputs):
|
|
|
|
|
def adv_search_text(q, include_inputs, exclude_inputs, data_value):
|
|
|
|
|
for inp in include_inputs:
|
|
|
|
|
q = q.filter(db.Books.data.any(data_value == inp))
|
|
|
|
|
for excl in exclude_inputs:
|
|
|
|
|
q = q.filter(not_(db.Books.data.any(data_value == excl)))
|
|
|
|
|
return q
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
'''def adv_search_extension(q, include_extension_inputs, exclude_extension_inputs):
|
|
|
|
|
for extension in include_extension_inputs:
|
|
|
|
|
q = q.filter(db.Books.data.any(db.Data.format == extension))
|
|
|
|
|
for extension in exclude_extension_inputs:
|
|
|
|
@ -1197,15 +1207,17 @@ def adv_search_serie(q, include_series_inputs, exclude_series_inputs):
|
|
|
|
|
q = q.filter(db.Books.series.any(db.Series.id == serie))
|
|
|
|
|
for serie in exclude_series_inputs:
|
|
|
|
|
q = q.filter(not_(db.Books.series.any(db.Series.id == serie)))
|
|
|
|
|
return q
|
|
|
|
|
return q'''
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def adv_search_shelf(q, include_shelf_inputs, exclude_shelf_inputs):
|
|
|
|
|
q = q.outerjoin(ub.BookShelf, db.Books.id == ub.BookShelf.book_id)\
|
|
|
|
|
q = q.outerjoin(ub.BookShelf, db.Books.id == ub.BookShelf.book_id) \
|
|
|
|
|
.filter(or_(ub.BookShelf.shelf == None, ub.BookShelf.shelf.notin_(exclude_shelf_inputs)))
|
|
|
|
|
if len(include_shelf_inputs) > 0:
|
|
|
|
|
q = q.filter(ub.BookShelf.shelf.in_(include_shelf_inputs))
|
|
|
|
|
return q
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def extend_search_term(searchterm,
|
|
|
|
|
author_name,
|
|
|
|
|
book_title,
|
|
|
|
@ -1232,7 +1244,7 @@ def extend_search_term(searchterm,
|
|
|
|
|
format='medium', locale=get_locale())])
|
|
|
|
|
except ValueError:
|
|
|
|
|
pub_end = u""
|
|
|
|
|
elements = {'tag': db.Tags, 'serie':db.Series, 'shelf':ub.Shelf}
|
|
|
|
|
elements = {'tag': db.Tags, 'serie': db.Series, 'shelf': ub.Shelf}
|
|
|
|
|
for key, db_element in elements.items():
|
|
|
|
|
tag_names = calibre_db.session.query(db_element).filter(db_element.id.in_(tags['include_' + key])).all()
|
|
|
|
|
searchterm.extend(tag.name for tag in tag_names)
|
|
|
|
@ -1284,8 +1296,8 @@ def render_adv_search_results(term, offset=None, order=None, limit=None):
|
|
|
|
|
query = query.outerjoin(ub.ArchivedBook, and_(db.Books.id == ub.ArchivedBook.book_id,
|
|
|
|
|
int(current_user.id) == ub.ArchivedBook.user_id))
|
|
|
|
|
|
|
|
|
|
q = query.outerjoin(db.books_series_link, db.Books.id == db.books_series_link.c.book)\
|
|
|
|
|
.outerjoin(db.Series)\
|
|
|
|
|
q = query.outerjoin(db.books_series_link, db.Books.id == db.books_series_link.c.book) \
|
|
|
|
|
.outerjoin(db.Series) \
|
|
|
|
|
.filter(calibre_db.common_filters(True))
|
|
|
|
|
|
|
|
|
|
# parse multiselects to a complete dict
|
|
|
|
@ -1311,43 +1323,43 @@ def render_adv_search_results(term, offset=None, order=None, limit=None):
|
|
|
|
|
if publisher:
|
|
|
|
|
publisher = publisher.strip().lower()
|
|
|
|
|
|
|
|
|
|
searchterm = []
|
|
|
|
|
search_term = []
|
|
|
|
|
cc_present = False
|
|
|
|
|
for c in cc:
|
|
|
|
|
if c.datatype == "datetime":
|
|
|
|
|
column_start = term.get('custom_column_' + str(c.id) + '_start')
|
|
|
|
|
column_end = term.get('custom_column_' + str(c.id) + '_end')
|
|
|
|
|
if column_start:
|
|
|
|
|
searchterm.extend([u"{} >= {}".format(c.name,
|
|
|
|
|
format_date(datetime.strptime(column_start, "%Y-%m-%d").date(),
|
|
|
|
|
format='medium',
|
|
|
|
|
locale=get_locale())
|
|
|
|
|
)])
|
|
|
|
|
search_term.extend([u"{} >= {}".format(c.name,
|
|
|
|
|
format_date(datetime.strptime(column_start, "%Y-%m-%d").date(),
|
|
|
|
|
format='medium',
|
|
|
|
|
locale=get_locale())
|
|
|
|
|
)])
|
|
|
|
|
cc_present = True
|
|
|
|
|
if column_end:
|
|
|
|
|
searchterm.extend([u"{} <= {}".format(c.name,
|
|
|
|
|
format_date(datetime.strptime(column_end, "%Y-%m-%d").date(),
|
|
|
|
|
format='medium',
|
|
|
|
|
locale=get_locale())
|
|
|
|
|
)])
|
|
|
|
|
search_term.extend([u"{} <= {}".format(c.name,
|
|
|
|
|
format_date(datetime.strptime(column_end, "%Y-%m-%d").date(),
|
|
|
|
|
format='medium',
|
|
|
|
|
locale=get_locale())
|
|
|
|
|
)])
|
|
|
|
|
cc_present = True
|
|
|
|
|
elif term.get('custom_column_' + str(c.id)):
|
|
|
|
|
searchterm.extend([(u"{}: {}".format(c.name, term.get('custom_column_' + str(c.id))))])
|
|
|
|
|
search_term.extend([(u"{}: {}".format(c.name, term.get('custom_column_' + str(c.id))))])
|
|
|
|
|
cc_present = True
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if any(tags.values()) or author_name or book_title or publisher or pub_start or pub_end or rating_low \
|
|
|
|
|
or rating_high or description or cc_present or read_status:
|
|
|
|
|
searchterm, pub_start, pub_end = extend_search_term(searchterm,
|
|
|
|
|
author_name,
|
|
|
|
|
book_title,
|
|
|
|
|
publisher,
|
|
|
|
|
pub_start,
|
|
|
|
|
pub_end,
|
|
|
|
|
tags,
|
|
|
|
|
rating_high,
|
|
|
|
|
rating_low,
|
|
|
|
|
read_status)
|
|
|
|
|
if any(tags.values()) or author_name or book_title or \
|
|
|
|
|
publisher or pub_start or pub_end or rating_low or rating_high \
|
|
|
|
|
or description or cc_present or read_status:
|
|
|
|
|
search_term, pub_start, pub_end = extend_search_term(search_term,
|
|
|
|
|
author_name,
|
|
|
|
|
book_title,
|
|
|
|
|
publisher,
|
|
|
|
|
pub_start,
|
|
|
|
|
pub_end,
|
|
|
|
|
tags,
|
|
|
|
|
rating_high,
|
|
|
|
|
rating_low,
|
|
|
|
|
read_status)
|
|
|
|
|
# q = q.filter()
|
|
|
|
|
if author_name:
|
|
|
|
|
q = q.filter(db.Books.authors.any(func.lower(db.Authors.name).ilike("%" + author_name + "%")))
|
|
|
|
@ -1360,12 +1372,12 @@ def render_adv_search_results(term, offset=None, order=None, limit=None):
|
|
|
|
|
q = adv_search_read_status(q, read_status)
|
|
|
|
|
if publisher:
|
|
|
|
|
q = q.filter(db.Books.publishers.any(func.lower(db.Publishers.name).ilike("%" + publisher + "%")))
|
|
|
|
|
q = adv_search_tag(q, tags['include_tag'], tags['exclude_tag'])
|
|
|
|
|
q = adv_search_serie(q, tags['include_serie'], tags['exclude_serie'])
|
|
|
|
|
q = adv_search_text(q, tags['include_tag'], tags['exclude_tag'], db.Tags.id)
|
|
|
|
|
q = adv_search_text(q, tags['include_serie'], tags['exclude_serie'], db.Series.id)
|
|
|
|
|
q = adv_search_text(q, tags['include_extension'], tags['exclude_extension'], db.Data.format)
|
|
|
|
|
q = adv_search_shelf(q, tags['include_shelf'], tags['exclude_shelf'])
|
|
|
|
|
q = adv_search_extension(q, tags['include_extension'], tags['exclude_extension'])
|
|
|
|
|
q = adv_search_language(q, tags['include_language'], tags['exclude_language'])
|
|
|
|
|
q = adv_search_ratings(q, rating_high, rating_low)
|
|
|
|
|
q = adv_search_language(q, tags['include_language'], tags['exclude_language'], )
|
|
|
|
|
q = adv_search_ratings(q, rating_high, rating_low, )
|
|
|
|
|
|
|
|
|
|
if description:
|
|
|
|
|
q = q.filter(db.Books.comments.any(func.lower(db.Comments.text).ilike("%" + description + "%")))
|
|
|
|
@ -1390,7 +1402,7 @@ def render_adv_search_results(term, offset=None, order=None, limit=None):
|
|
|
|
|
limit_all = result_count
|
|
|
|
|
entries = calibre_db.order_authors(q[offset:limit_all], list_return=True, combined=True)
|
|
|
|
|
return render_title_template('search.html',
|
|
|
|
|
adv_searchterm=searchterm,
|
|
|
|
|
adv_searchterm=search_term,
|
|
|
|
|
pagination=pagination,
|
|
|
|
|
entries=entries,
|
|
|
|
|
result_count=result_count,
|
|
|
|
@ -1414,10 +1426,12 @@ def advanced_search_form():
|
|
|
|
|
def get_cover(book_id):
|
|
|
|
|
return get_book_cover(book_id)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@web.route("/robots.txt")
|
|
|
|
|
def get_robots():
|
|
|
|
|
return send_from_directory(constants.STATIC_DIR, "robots.txt")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@web.route("/show/<int:book_id>/<book_format>", defaults={'anyname': 'None'})
|
|
|
|
|
@web.route("/show/<int:book_id>/<book_format>/<anyname>")
|
|
|
|
|
@login_required_if_no_ano
|
|
|
|
@ -1561,7 +1575,7 @@ def login():
|
|
|
|
|
category="success")
|
|
|
|
|
return redirect_back(url_for("web.index"))
|
|
|
|
|
elif login_result is None and user and check_password_hash(str(user.password), form['password']) \
|
|
|
|
|
and user.name != "Guest":
|
|
|
|
|
and user.name != "Guest":
|
|
|
|
|
login_user(user, remember=bool(form.get('remember_me')))
|
|
|
|
|
ub.store_user_session()
|
|
|
|
|
log.info("Local Fallback Login as: '%s'", user.name)
|
|
|
|
@ -1573,23 +1587,23 @@ def login():
|
|
|
|
|
log.info(error)
|
|
|
|
|
flash(_(u"Could not login: %(message)s", message=error), category="error")
|
|
|
|
|
else:
|
|
|
|
|
ip_Address = request.headers.get('X-Forwarded-For', request.remote_addr)
|
|
|
|
|
log.warning('LDAP Login failed for user "%s" IP-address: %s', form['username'], ip_Address)
|
|
|
|
|
ip_address = request.headers.get('X-Forwarded-For', request.remote_addr)
|
|
|
|
|
log.warning('LDAP Login failed for user "%s" IP-address: %s', form['username'], ip_address)
|
|
|
|
|
flash(_(u"Wrong Username or Password"), category="error")
|
|
|
|
|
else:
|
|
|
|
|
ip_Address = request.headers.get('X-Forwarded-For', request.remote_addr)
|
|
|
|
|
ip_address = request.headers.get('X-Forwarded-For', request.remote_addr)
|
|
|
|
|
if 'forgot' in form and form['forgot'] == 'forgot':
|
|
|
|
|
if user is not None and user.name != "Guest":
|
|
|
|
|
ret, __ = reset_password(user.id)
|
|
|
|
|
if ret == 1:
|
|
|
|
|
flash(_(u"New Password was send to your email address"), category="info")
|
|
|
|
|
log.info('Password reset for user "%s" IP-address: %s', form['username'], ip_Address)
|
|
|
|
|
log.info('Password reset for user "%s" IP-address: %s', form['username'], ip_address)
|
|
|
|
|
else:
|
|
|
|
|
log.error(u"An unknown error occurred. Please try again later")
|
|
|
|
|
flash(_(u"An unknown error occurred. Please try again later."), category="error")
|
|
|
|
|
else:
|
|
|
|
|
flash(_(u"Please enter valid username to reset password"), category="error")
|
|
|
|
|
log.warning('Username missing for password reset IP-address: %s', ip_Address)
|
|
|
|
|
log.warning('Username missing for password reset IP-address: %s', ip_address)
|
|
|
|
|
else:
|
|
|
|
|
if user and check_password_hash(str(user.password), form['password']) and user.name != "Guest":
|
|
|
|
|
login_user(user, remember=bool(form.get('remember_me')))
|
|
|
|
@ -1599,7 +1613,7 @@ def login():
|
|
|
|
|
config.config_is_initial = False
|
|
|
|
|
return redirect_back(url_for("web.index"))
|
|
|
|
|
else:
|
|
|
|
|
log.warning('Login failed for user "%s" IP-address: %s', form['username'], ip_Address)
|
|
|
|
|
log.warning('Login failed for user "%s" IP-address: %s', form['username'], ip_address)
|
|
|
|
|
flash(_(u"Wrong Username or Password"), category="error")
|
|
|
|
|
|
|
|
|
|
next_url = request.args.get('next', default=url_for("web.index"), type=str)
|
|
|
|
@ -1617,7 +1631,7 @@ def login():
|
|
|
|
|
@login_required
|
|
|
|
|
def logout():
|
|
|
|
|
if current_user is not None and current_user.is_authenticated:
|
|
|
|
|
ub.delete_user_session(current_user.id, flask_session.get('_id',""))
|
|
|
|
|
ub.delete_user_session(current_user.id, flask_session.get('_id', ""))
|
|
|
|
|
logout_user()
|
|
|
|
|
if feature_support['oauth'] and (config.config_login_type == 2 or config.config_login_type == 3):
|
|
|
|
|
logout_oauth_user()
|
|
|
|
@ -1639,7 +1653,7 @@ def change_profile(kobo_support, local_oauth_check, oauth_status, translations,
|
|
|
|
|
current_user.email = check_email(to_save["email"])
|
|
|
|
|
if current_user.role_admin():
|
|
|
|
|
if to_save.get("name", current_user.name) != current_user.name:
|
|
|
|
|
# Query User name, if not existing, change
|
|
|
|
|
# Query username, if not existing, change
|
|
|
|
|
current_user.name = check_username(to_save["name"])
|
|
|
|
|
current_user.random_books = 1 if to_save.get("show_random") == "on" else 0
|
|
|
|
|
if to_save.get("default_language"):
|
|
|
|
@ -1693,7 +1707,7 @@ def change_profile(kobo_support, local_oauth_check, oauth_status, translations,
|
|
|
|
|
@login_required
|
|
|
|
|
def profile():
|
|
|
|
|
languages = calibre_db.speaking_language()
|
|
|
|
|
translations = babel.list_translations() + [LC('en')]
|
|
|
|
|
translations = babel.list_translations() + [Locale('en')]
|
|
|
|
|
kobo_support = feature_support['kobo'] and config.config_kobo_sync
|
|
|
|
|
if feature_support['oauth'] and config.config_login_type == 2:
|
|
|
|
|
oauth_status = get_oauth_status()
|
|
|
|
@ -1727,7 +1741,8 @@ def read_book(book_id, book_format):
|
|
|
|
|
book.ordered_authors = calibre_db.order_authors([book], False)
|
|
|
|
|
|
|
|
|
|
if not book:
|
|
|
|
|
flash(_(u"Oops! Selected book title is unavailable. File does not exist or is not accessible"), category="error")
|
|
|
|
|
flash(_(u"Oops! Selected book title is unavailable. File does not exist or is not accessible"),
|
|
|
|
|
category="error")
|
|
|
|
|
log.debug(u"Oops! Selected book title is unavailable. File does not exist or is not accessible")
|
|
|
|
|
return redirect(url_for("web.index"))
|
|
|
|
|
|
|
|
|
@ -1768,7 +1783,8 @@ def read_book(book_id, book_format):
|
|
|
|
|
return render_title_template('readcbr.html', comicfile=all_name, title=title,
|
|
|
|
|
extension=fileExt)
|
|
|
|
|
log.debug(u"Oops! Selected book title is unavailable. File does not exist or is not accessible")
|
|
|
|
|
flash(_(u"Oops! Selected book title is unavailable. File does not exist or is not accessible"), category="error")
|
|
|
|
|
flash(_(u"Oops! Selected book title is unavailable. File does not exist or is not accessible"),
|
|
|
|
|
category="error")
|
|
|
|
|
return redirect(url_for("web.index"))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -1782,14 +1798,14 @@ def show_book(book_id):
|
|
|
|
|
entry = entries[0]
|
|
|
|
|
entry.read_status = read_book == ub.ReadBook.STATUS_FINISHED
|
|
|
|
|
entry.is_archived = archived_book
|
|
|
|
|
for index in range(0, len(entry.languages)):
|
|
|
|
|
entry.languages[index].language_name = isoLanguages.get_language_name(get_locale(), entry.languages[
|
|
|
|
|
index].lang_code)
|
|
|
|
|
for lang_index in range(0, len(entry.languages)):
|
|
|
|
|
entry.languages[lang_index].language_name = isoLanguages.get_language_name(get_locale(), entry.languages[
|
|
|
|
|
lang_index].lang_code)
|
|
|
|
|
cc = get_cc_columns(filter_config_custom_read=True)
|
|
|
|
|
book_in_shelfs = []
|
|
|
|
|
book_in_shelves = []
|
|
|
|
|
shelfs = ub.session.query(ub.BookShelf).filter(ub.BookShelf.book_id == book_id).all()
|
|
|
|
|
for sh in shelfs:
|
|
|
|
|
book_in_shelfs.append(sh.shelf)
|
|
|
|
|
book_in_shelves.append(sh.shelf)
|
|
|
|
|
|
|
|
|
|
entry.tags = sort(entry.tags, key=lambda tag: tag.name)
|
|
|
|
|
|
|
|
|
@ -1806,9 +1822,9 @@ def show_book(book_id):
|
|
|
|
|
return render_title_template('detail.html',
|
|
|
|
|
entry=entry,
|
|
|
|
|
cc=cc,
|
|
|
|
|
is_xhr=request.headers.get('X-Requested-With')=='XMLHttpRequest',
|
|
|
|
|
is_xhr=request.headers.get('X-Requested-With') == 'XMLHttpRequest',
|
|
|
|
|
title=entry.title,
|
|
|
|
|
books_shelfs=book_in_shelfs,
|
|
|
|
|
books_shelfs=book_in_shelves,
|
|
|
|
|
page="book")
|
|
|
|
|
else:
|
|
|
|
|
log.debug(u"Oops! Selected book title is unavailable. File does not exist or is not accessible")
|
|
|
|
|