mirror of
				https://github.com/janeczku/calibre-web
				synced 2025-10-30 23:03:02 +00:00 
			
		
		
		
	Refactored load read status for web access and opds access
Refactored and removed discover html page Bugfix show author Bugfix open dialog in author page Fix for #2341 (advanced search with linked read column and read column having a higher number than number of available custom columns)
This commit is contained in:
		
							
								
								
									
										53
									
								
								cps/db.py
									
									
									
									
									
								
							
							
						
						
									
										53
									
								
								cps/db.py
									
									
									
									
									
								
							| @@ -680,6 +680,25 @@ class CalibreDB: | |||||||
|         return and_(lang_filter, pos_content_tags_filter, ~neg_content_tags_filter, |         return and_(lang_filter, pos_content_tags_filter, ~neg_content_tags_filter, | ||||||
|                     pos_content_cc_filter, ~neg_content_cc_filter, archived_filter) |                     pos_content_cc_filter, ~neg_content_cc_filter, archived_filter) | ||||||
|  |  | ||||||
|  |     def generate_linked_query(self, config_read_column, database): | ||||||
|  |         if not config_read_column: | ||||||
|  |             query = (self.session.query(database, ub.ArchivedBook.is_archived, ub.ReadBook.read_status) | ||||||
|  |                      .select_from(Books) | ||||||
|  |                      .outerjoin(ub.ReadBook, | ||||||
|  |                                 and_(ub.ReadBook.user_id == int(current_user.id), ub.ReadBook.book_id == Books.id))) | ||||||
|  |         else: | ||||||
|  |             try: | ||||||
|  |                 read_column = cc_classes[config_read_column] | ||||||
|  |                 query = (self.session.query(database, ub.ArchivedBook.is_archived, read_column.value) | ||||||
|  |                          .select_from(Books) | ||||||
|  |                          .outerjoin(read_column, read_column.book == Books.id)) | ||||||
|  |             except (KeyError, AttributeError, IndexError): | ||||||
|  |                 log.error("Custom Column No.{} is not existing in calibre database".format(config_read_column)) | ||||||
|  |                 # Skip linking read column and return None instead of read status | ||||||
|  |                 query = self.session.query(database, None, ub.ArchivedBook.is_archived) | ||||||
|  |         return query.outerjoin(ub.ArchivedBook, and_(Books.id == ub.ArchivedBook.book_id, | ||||||
|  |                                                      int(current_user.id) == ub.ArchivedBook.user_id)) | ||||||
|  |  | ||||||
|     @staticmethod |     @staticmethod | ||||||
|     def get_checkbox_sorted(inputlist, state, offset, limit, order, combo=False): |     def get_checkbox_sorted(inputlist, state, offset, limit, order, combo=False): | ||||||
|         outcome = list() |         outcome = list() | ||||||
| @@ -709,30 +728,14 @@ class CalibreDB: | |||||||
|                                            join_archive_read, config_read_column, *join): |                                            join_archive_read, config_read_column, *join): | ||||||
|         pagesize = pagesize or self.config.config_books_per_page |         pagesize = pagesize or self.config.config_books_per_page | ||||||
|         if current_user.show_detail_random(): |         if current_user.show_detail_random(): | ||||||
|             randm = self.session.query(Books) \ |             random_query = self.generate_linked_query(config_read_column, database) | ||||||
|                 .filter(self.common_filters(allow_show_archived)) \ |             randm = (random_query.filter(self.common_filters(allow_show_archived)) | ||||||
|                 .order_by(func.random()) \ |                      .order_by(func.random()) | ||||||
|                 .limit(self.config.config_random_books).all() |                      .limit(self.config.config_random_books).all()) | ||||||
|         else: |         else: | ||||||
|             randm = false() |             randm = false() | ||||||
|         if join_archive_read: |         if join_archive_read: | ||||||
|             if not config_read_column: |             query = self.generate_linked_query(config_read_column, database) | ||||||
|                 query = (self.session.query(database, ub.ReadBook.read_status, ub.ArchivedBook.is_archived) |  | ||||||
|                          .select_from(Books) |  | ||||||
|                          .outerjoin(ub.ReadBook, |  | ||||||
|                                     and_(ub.ReadBook.user_id == int(current_user.id), ub.ReadBook.book_id == Books.id))) |  | ||||||
|             else: |  | ||||||
|                 try: |  | ||||||
|                     read_column = cc_classes[config_read_column] |  | ||||||
|                     query = (self.session.query(database, read_column.value, ub.ArchivedBook.is_archived) |  | ||||||
|                              .select_from(Books) |  | ||||||
|                              .outerjoin(read_column, read_column.book == Books.id)) |  | ||||||
|                 except (KeyError, AttributeError, IndexError): |  | ||||||
|                     log.error("Custom Column No.{} is not existing in calibre database".format(read_column)) |  | ||||||
|                     # Skip linking read column and return None instead of read status |  | ||||||
|                     query = self.session.query(database, None, ub.ArchivedBook.is_archived) |  | ||||||
|             query = query.outerjoin(ub.ArchivedBook, and_(Books.id == ub.ArchivedBook.book_id, |  | ||||||
|                                                           int(current_user.id) == ub.ArchivedBook.user_id)) |  | ||||||
|         else: |         else: | ||||||
|             query = self.session.query(database) |             query = self.session.query(database) | ||||||
|         off = int(int(pagesize) * (page - 1)) |         off = int(int(pagesize) * (page - 1)) | ||||||
| @@ -830,21 +833,23 @@ class CalibreDB: | |||||||
|         authorterms = re.split("[, ]+", term) |         authorterms = re.split("[, ]+", term) | ||||||
|         for authorterm in authorterms: |         for authorterm in authorterms: | ||||||
|             q.append(Books.authors.any(func.lower(Authors.name).ilike("%" + authorterm + "%"))) |             q.append(Books.authors.any(func.lower(Authors.name).ilike("%" + authorterm + "%"))) | ||||||
|         if not config_read_column: |         query = self.generate_linked_query(config_read_column, Books) | ||||||
|  |         '''if not config_read_column: | ||||||
|             query = (self.session.query(Books, ub.ArchivedBook.is_archived, ub.ReadBook).select_from(Books) |             query = (self.session.query(Books, ub.ArchivedBook.is_archived, ub.ReadBook).select_from(Books) | ||||||
|                      .outerjoin(ub.ReadBook, and_(Books.id == ub.ReadBook.book_id, |                      .outerjoin(ub.ReadBook, and_(Books.id == ub.ReadBook.book_id, | ||||||
|                                                   int(current_user.id) == ub.ReadBook.user_id))) |                                                   int(current_user.id) == ub.ReadBook.user_id))) | ||||||
|         else: |         else: | ||||||
|             try: |             try: | ||||||
|                 read_column = cc_classes[config_read_column] |                 read_column = cc_classes[config_read_column] | ||||||
|                 query = (self.session.query(Books, ub.ArchivedBook.is_archived, read_column.value).select_from(Books) |                 query = (self.session.query(Books, ub.ArchivedBook.is_archived, read_column.value) | ||||||
|  |                          .select_from(Books) | ||||||
|                          .outerjoin(read_column, read_column.book == Books.id)) |                          .outerjoin(read_column, read_column.book == Books.id)) | ||||||
|             except (KeyError, AttributeError, IndexError): |             except (KeyError, AttributeError, IndexError): | ||||||
|                 log.error("Custom Column No.{} is not existing in calibre database".format(config_read_column)) |                 log.error("Custom Column No.{} is not existing in calibre database".format(config_read_column)) | ||||||
|                 # Skip linking read column |                 # Skip linking read column | ||||||
|                 query = self.session.query(Books, ub.ArchivedBook.is_archived, None) |                 query = self.session.query(Books, ub.ArchivedBook.is_archived, None) | ||||||
|         query = query.outerjoin(ub.ArchivedBook, and_(Books.id == ub.ArchivedBook.book_id, |         query = query.outerjoin(ub.ArchivedBook, and_(Books.id == ub.ArchivedBook.book_id, | ||||||
|                                                       int(current_user.id) == ub.ArchivedBook.user_id)) |                                                       int(current_user.id) == ub.ArchivedBook.user_id))''' | ||||||
|  |  | ||||||
|         if len(join) == 6: |         if len(join) == 6: | ||||||
|             query = query.outerjoin(join[0], join[1]).outerjoin(join[2]).outerjoin(join[3], join[4]).outerjoin(join[5]) |             query = query.outerjoin(join[0], join[1]).outerjoin(join[2]).outerjoin(join[3], join[4]).outerjoin(join[5]) | ||||||
|   | |||||||
							
								
								
									
										68
									
								
								cps/opds.py
									
									
									
									
									
								
							
							
						
						
									
										68
									
								
								cps/opds.py
									
									
									
									
									
								
							| @@ -26,7 +26,8 @@ from functools import wraps | |||||||
|  |  | ||||||
| from flask import Blueprint, request, render_template, Response, g, make_response, abort | from flask import Blueprint, request, render_template, Response, g, make_response, abort | ||||||
| from flask_login import current_user | from flask_login import current_user | ||||||
| from sqlalchemy.sql.expression import func, text, or_, and_, any_, true | from sqlalchemy.sql.expression import func, text, or_, and_, true | ||||||
|  | from sqlalchemy.exc import InvalidRequestError, OperationalError | ||||||
| from werkzeug.security import check_password_hash | from werkzeug.security import check_password_hash | ||||||
| from . import constants, logger, config, db, calibre_db, ub, services, get_locale, isoLanguages | from . import constants, logger, config, db, calibre_db, ub, services, get_locale, isoLanguages | ||||||
| from .helper import get_download_link, get_book_cover | from .helper import get_download_link, get_book_cover | ||||||
| @@ -108,7 +109,8 @@ def feed_letter_books(book_id): | |||||||
|     entries, __, pagination = calibre_db.fill_indexpage((int(off) / (int(config.config_books_per_page)) + 1), 0, |     entries, __, pagination = calibre_db.fill_indexpage((int(off) / (int(config.config_books_per_page)) + 1), 0, | ||||||
|                                                         db.Books, |                                                         db.Books, | ||||||
|                                                         letter, |                                                         letter, | ||||||
|                                                         [db.Books.sort]) |                                                         [db.Books.sort], | ||||||
|  |                                                         True, config.config_read_column) | ||||||
|  |  | ||||||
|     return render_xml_template('feed.xml', entries=entries, pagination=pagination) |     return render_xml_template('feed.xml', entries=entries, pagination=pagination) | ||||||
|  |  | ||||||
| @@ -118,15 +120,16 @@ def feed_letter_books(book_id): | |||||||
| def feed_new(): | def feed_new(): | ||||||
|     off = request.args.get("offset") or 0 |     off = request.args.get("offset") or 0 | ||||||
|     entries, __, pagination = calibre_db.fill_indexpage((int(off) / (int(config.config_books_per_page)) + 1), 0, |     entries, __, pagination = calibre_db.fill_indexpage((int(off) / (int(config.config_books_per_page)) + 1), 0, | ||||||
|                                                         db.Books, True, [db.Books.timestamp.desc()]) |                                                         db.Books, True, [db.Books.timestamp.desc()], | ||||||
|  |                                                         True, config.config_read_column) | ||||||
|     return render_xml_template('feed.xml', entries=entries, pagination=pagination) |     return render_xml_template('feed.xml', entries=entries, pagination=pagination) | ||||||
|  |  | ||||||
|  |  | ||||||
| @opds.route("/opds/discover") | @opds.route("/opds/discover") | ||||||
| @requires_basic_auth_if_no_ano | @requires_basic_auth_if_no_ano | ||||||
| def feed_discover(): | def feed_discover(): | ||||||
|     entries = calibre_db.session.query(db.Books).filter(calibre_db.common_filters()).order_by(func.random())\ |     query = calibre_db.generate_linked_query(config.config_read_column, db.Books) | ||||||
|         .limit(config.config_books_per_page) |     entries = query.filter(calibre_db.common_filters()).order_by(func.random()).limit(config.config_books_per_page) | ||||||
|     pagination = Pagination(1, config.config_books_per_page, int(config.config_books_per_page)) |     pagination = Pagination(1, config.config_books_per_page, int(config.config_books_per_page)) | ||||||
|     return render_xml_template('feed.xml', entries=entries, pagination=pagination) |     return render_xml_template('feed.xml', entries=entries, pagination=pagination) | ||||||
|  |  | ||||||
| @@ -137,7 +140,8 @@ def feed_best_rated(): | |||||||
|     off = request.args.get("offset") or 0 |     off = request.args.get("offset") or 0 | ||||||
|     entries, __, pagination = calibre_db.fill_indexpage((int(off) / (int(config.config_books_per_page)) + 1), 0, |     entries, __, pagination = calibre_db.fill_indexpage((int(off) / (int(config.config_books_per_page)) + 1), 0, | ||||||
|                                                         db.Books, db.Books.ratings.any(db.Ratings.rating > 9), |                                                         db.Books, db.Books.ratings.any(db.Ratings.rating > 9), | ||||||
|                                                         [db.Books.timestamp.desc()]) |                                                         [db.Books.timestamp.desc()], | ||||||
|  |                                                         True, config.config_read_column) | ||||||
|     return render_xml_template('feed.xml', entries=entries, pagination=pagination) |     return render_xml_template('feed.xml', entries=entries, pagination=pagination) | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -150,11 +154,11 @@ def feed_hot(): | |||||||
|     hot_books = all_books.offset(off).limit(config.config_books_per_page) |     hot_books = all_books.offset(off).limit(config.config_books_per_page) | ||||||
|     entries = list() |     entries = list() | ||||||
|     for book in hot_books: |     for book in hot_books: | ||||||
|         download_book = calibre_db.get_book(book.Downloads.book_id) |         query = calibre_db.generate_linked_query(config.config_read_column, db.Books) | ||||||
|  |         download_book = query.filter(calibre_db.common_filters()).filter( | ||||||
|  |             book.Downloads.book_id == db.Books.id).first() | ||||||
|         if download_book: |         if download_book: | ||||||
|             entries.append( |             entries.append(download_book) | ||||||
|                 calibre_db.get_filtered_book(book.Downloads.book_id) |  | ||||||
|             ) |  | ||||||
|         else: |         else: | ||||||
|             ub.delete_download(book.Downloads.book_id) |             ub.delete_download(book.Downloads.book_id) | ||||||
|     num_books = entries.__len__() |     num_books = entries.__len__() | ||||||
| @@ -270,7 +274,8 @@ def feed_series(book_id): | |||||||
|     entries, __, pagination = calibre_db.fill_indexpage((int(off) / (int(config.config_books_per_page)) + 1), 0, |     entries, __, pagination = calibre_db.fill_indexpage((int(off) / (int(config.config_books_per_page)) + 1), 0, | ||||||
|                                                         db.Books, |                                                         db.Books, | ||||||
|                                                         db.Books.series.any(db.Series.id == book_id), |                                                         db.Books.series.any(db.Series.id == book_id), | ||||||
|                                                         [db.Books.series_index]) |                                                         [db.Books.series_index], | ||||||
|  |                                                         True, config.config_read_column) | ||||||
|     return render_xml_template('feed.xml', entries=entries, pagination=pagination) |     return render_xml_template('feed.xml', entries=entries, pagination=pagination) | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -324,7 +329,8 @@ def feed_format(book_id): | |||||||
|     entries, __, pagination = calibre_db.fill_indexpage((int(off) / (int(config.config_books_per_page)) + 1), 0, |     entries, __, pagination = calibre_db.fill_indexpage((int(off) / (int(config.config_books_per_page)) + 1), 0, | ||||||
|                                                         db.Books, |                                                         db.Books, | ||||||
|                                                         db.Books.data.any(db.Data.format == book_id.upper()), |                                                         db.Books.data.any(db.Data.format == book_id.upper()), | ||||||
|                                                         [db.Books.timestamp.desc()]) |                                                         [db.Books.timestamp.desc()], | ||||||
|  |                                                         True, config.config_read_column) | ||||||
|     return render_xml_template('feed.xml', entries=entries, pagination=pagination) |     return render_xml_template('feed.xml', entries=entries, pagination=pagination) | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -351,7 +357,8 @@ def feed_languages(book_id): | |||||||
|     entries, __, pagination = calibre_db.fill_indexpage((int(off) / (int(config.config_books_per_page)) + 1), 0, |     entries, __, pagination = calibre_db.fill_indexpage((int(off) / (int(config.config_books_per_page)) + 1), 0, | ||||||
|                                                         db.Books, |                                                         db.Books, | ||||||
|                                                         db.Books.languages.any(db.Languages.id == book_id), |                                                         db.Books.languages.any(db.Languages.id == book_id), | ||||||
|                                                         [db.Books.timestamp.desc()]) |                                                         [db.Books.timestamp.desc()], | ||||||
|  |                                                         True, config.config_read_column) | ||||||
|     return render_xml_template('feed.xml', entries=entries, pagination=pagination) |     return render_xml_template('feed.xml', entries=entries, pagination=pagination) | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -381,13 +388,25 @@ def feed_shelf(book_id): | |||||||
|     result = list() |     result = list() | ||||||
|     # user is allowed to access shelf |     # user is allowed to access shelf | ||||||
|     if shelf: |     if shelf: | ||||||
|         books_in_shelf = ub.session.query(ub.BookShelf).filter(ub.BookShelf.shelf == book_id).order_by( |         result, __, pagination = calibre_db.fill_indexpage((int(off) / (int(config.config_books_per_page)) + 1), | ||||||
|             ub.BookShelf.order.asc()).all() |                                                            config.config_books_per_page, | ||||||
|         for book in books_in_shelf: |                                                            db.Books, | ||||||
|             cur_book = calibre_db.get_book(book.book_id) |                                                            ub.BookShelf.shelf == shelf.id, | ||||||
|             result.append(cur_book) |                                                            [ub.BookShelf.order.asc()], | ||||||
|     pagination = Pagination((int(off) / (int(config.config_books_per_page)) + 1), config.config_books_per_page, |                                                            True, config.config_read_column, | ||||||
|                             len(result)) |                                                            ub.BookShelf, ub.BookShelf.book_id == db.Books.id) | ||||||
|  |         # delete shelf entries where book is not existent anymore, can happen if book is deleted outside calibre-web | ||||||
|  |         wrong_entries = calibre_db.session.query(ub.BookShelf) \ | ||||||
|  |             .join(db.Books, ub.BookShelf.book_id == db.Books.id, isouter=True) \ | ||||||
|  |             .filter(db.Books.id == None).all() | ||||||
|  |         for entry in wrong_entries: | ||||||
|  |             log.info('Not existing book {} in {} deleted'.format(entry.book_id, shelf)) | ||||||
|  |             try: | ||||||
|  |                 ub.session.query(ub.BookShelf).filter(ub.BookShelf.book_id == entry.book_id).delete() | ||||||
|  |                 ub.session.commit() | ||||||
|  |             except (OperationalError, InvalidRequestError) as e: | ||||||
|  |                 ub.session.rollback() | ||||||
|  |                 log.error_or_exception("Settings Database error: {}".format(e)) | ||||||
|     return render_xml_template('feed.xml', entries=result, pagination=pagination) |     return render_xml_template('feed.xml', entries=result, pagination=pagination) | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -451,8 +470,7 @@ def feed_search(term): | |||||||
|         entries, __, ___ = calibre_db.get_search_results(term, config_read_column=config.config_read_column) |         entries, __, ___ = calibre_db.get_search_results(term, config_read_column=config.config_read_column) | ||||||
|         entries_count = len(entries) if len(entries) > 0 else 1 |         entries_count = len(entries) if len(entries) > 0 else 1 | ||||||
|         pagination = Pagination(1, entries_count, entries_count) |         pagination = Pagination(1, entries_count, entries_count) | ||||||
|         items = [entry[0] for entry in entries] |         return render_xml_template('feed.xml', searchterm=term, entries=entries, pagination=pagination) | ||||||
|         return render_xml_template('feed.xml', searchterm=term, entries=items, pagination=pagination) |  | ||||||
|     else: |     else: | ||||||
|         return render_xml_template('feed.xml', searchterm="") |         return render_xml_template('feed.xml', searchterm="") | ||||||
|  |  | ||||||
| @@ -493,14 +511,16 @@ def render_xml_dataset(data_table, book_id): | |||||||
|     entries, __, pagination = calibre_db.fill_indexpage((int(off) / (int(config.config_books_per_page)) + 1), 0, |     entries, __, pagination = calibre_db.fill_indexpage((int(off) / (int(config.config_books_per_page)) + 1), 0, | ||||||
|                                                         db.Books, |                                                         db.Books, | ||||||
|                                                         getattr(db.Books, data_table.__tablename__).any(data_table.id == book_id), |                                                         getattr(db.Books, data_table.__tablename__).any(data_table.id == book_id), | ||||||
|                                                         [db.Books.timestamp.desc()]) |                                                         [db.Books.timestamp.desc()], | ||||||
|  |                                                         True, config.config_read_column) | ||||||
|     return render_xml_template('feed.xml', entries=entries, pagination=pagination) |     return render_xml_template('feed.xml', entries=entries, pagination=pagination) | ||||||
|  |  | ||||||
|  |  | ||||||
| def render_element_index(database_column, linked_table, folder): | def render_element_index(database_column, linked_table, folder): | ||||||
|     shift = 0 |     shift = 0 | ||||||
|     off = int(request.args.get("offset") or 0) |     off = int(request.args.get("offset") or 0) | ||||||
|     entries = calibre_db.session.query(func.upper(func.substr(database_column, 1, 1)).label('id')) |     entries = calibre_db.session.query(func.upper(func.substr(database_column, 1, 1)).label('id'), None, None) | ||||||
|  |     # query = calibre_db.generate_linked_query(config.config_read_column, db.Books) | ||||||
|     if linked_table is not None: |     if linked_table is not None: | ||||||
|         entries = entries.join(linked_table).join(db.Books) |         entries = entries.join(linked_table).join(db.Books) | ||||||
|     entries = entries.filter(calibre_db.common_filters()).group_by(func.upper(func.substr(database_column, 1, 1))).all() |     entries = entries.filter(calibre_db.common_filters()).group_by(func.upper(func.substr(database_column, 1, 1))).all() | ||||||
|   | |||||||
| @@ -101,7 +101,7 @@ def get_sidebar_config(kwargs=None): | |||||||
|              "show_text": _('Show Books List'), "config_show": content}) |              "show_text": _('Show Books List'), "config_show": content}) | ||||||
|     return sidebar, simple |     return sidebar, simple | ||||||
|  |  | ||||||
| def get_readbooks_ids(): | '''def get_readbooks_ids(): | ||||||
|     if not config.config_read_column: |     if not config.config_read_column: | ||||||
|         readBooks = ub.session.query(ub.ReadBook).filter(ub.ReadBook.user_id == int(current_user.id))\ |         readBooks = ub.session.query(ub.ReadBook).filter(ub.ReadBook.user_id == int(current_user.id))\ | ||||||
|             .filter(ub.ReadBook.read_status == ub.ReadBook.STATUS_FINISHED).all() |             .filter(ub.ReadBook.read_status == ub.ReadBook.STATUS_FINISHED).all() | ||||||
| @@ -113,11 +113,11 @@ def get_readbooks_ids(): | |||||||
|             return frozenset([x.book for x in readBooks]) |             return frozenset([x.book for x in readBooks]) | ||||||
|         except (KeyError, AttributeError, IndexError): |         except (KeyError, AttributeError, IndexError): | ||||||
|             log.error("Custom Column No.{} is not existing in calibre database".format(config.config_read_column)) |             log.error("Custom Column No.{} is not existing in calibre database".format(config.config_read_column)) | ||||||
|             return [] |             return []''' | ||||||
|  |  | ||||||
| # Returns the template for rendering and includes the instance name | # Returns the template for rendering and includes the instance name | ||||||
| def render_title_template(*args, **kwargs): | def render_title_template(*args, **kwargs): | ||||||
|     sidebar, simple = get_sidebar_config(kwargs) |     sidebar, simple = get_sidebar_config(kwargs) | ||||||
|     return render_template(instance=config.config_calibre_web_title, sidebar=sidebar, simple=simple, |     return render_template(instance=config.config_calibre_web_title, sidebar=sidebar, simple=simple, | ||||||
|                            accept=constants.EXTENSIONS_UPLOAD, read_book_ids=get_readbooks_ids(), |                            accept=constants.EXTENSIONS_UPLOAD, # read_book_ids=get_readbooks_ids(), | ||||||
|                            *args, **kwargs) |                            *args, **kwargs) | ||||||
|   | |||||||
| @@ -439,7 +439,7 @@ def render_show_shelf(shelf_type, shelf_id, page_no, sort_param): | |||||||
|                                                            db.Books, |                                                            db.Books, | ||||||
|                                                            ub.BookShelf.shelf == shelf_id, |                                                            ub.BookShelf.shelf == shelf_id, | ||||||
|                                                            [ub.BookShelf.order.asc()], |                                                            [ub.BookShelf.order.asc()], | ||||||
|                                                            False, 0, |                                                            True, config.config_read_column, | ||||||
|                                                            ub.BookShelf, ub.BookShelf.book_id == db.Books.id) |                                                            ub.BookShelf, ub.BookShelf.book_id == db.Books.id) | ||||||
|         # delete chelf entries where book is not existent anymore, can happen if book is deleted outside calibre-web |         # delete chelf entries where book is not existent anymore, can happen if book is deleted outside calibre-web | ||||||
|         wrong_entries = calibre_db.session.query(ub.BookShelf) \ |         wrong_entries = calibre_db.session.query(ub.BookShelf) \ | ||||||
|   | |||||||
| @@ -31,23 +31,22 @@ | |||||||
|       <a id="pub_old" data-toggle="tooltip" title="{{_('Sort according to publishing date, oldest first')}}" class="btn btn-primary{% if order == "pubold" %} active{% endif%}" href="{{url_for('web.books_list', data='author', book_id=id, sort_param='pubold')}}"><span class="glyphicon glyphicon-calendar"></span><span class="glyphicon glyphicon-sort-by-order-alt"></span></a> |       <a id="pub_old" data-toggle="tooltip" title="{{_('Sort according to publishing date, oldest first')}}" class="btn btn-primary{% if order == "pubold" %} active{% endif%}" href="{{url_for('web.books_list', data='author', book_id=id, sort_param='pubold')}}"><span class="glyphicon glyphicon-calendar"></span><span class="glyphicon glyphicon-sort-by-order-alt"></span></a> | ||||||
|     </div> |     </div> | ||||||
|   <div class="row display-flex"> |   <div class="row display-flex"> | ||||||
|     {% if entries[0] %} |  | ||||||
|     {% for entry in entries %} |     {% for entry in entries %} | ||||||
|     <div id="books" class="col-sm-3 col-lg-2 col-xs-6 book"> |     <div id="books" class="col-sm-3 col-lg-2 col-xs-6 book"> | ||||||
|       <div class="cover"> |       <div class="cover"> | ||||||
|         <a href="{{ url_for('web.show_book', book_id=entry.id) }}"> |         <a href="{{ url_for('web.show_book', book_id=entry.Books.id) }}" {% if simple==false %}data-toggle="modal" data-target="#bookDetailsModal" data-remote="false"{% endif %}> | ||||||
|             <span class="img" title="{{entry.title}}"> |             <span class="img" title="{{entry.Books.title}}"> | ||||||
|               <img src="{{ url_for('web.get_cover', book_id=entry.id) }}" /> |               <img src="{{ url_for('web.get_cover', book_id=entry.Books.id) }}" /> | ||||||
|               {% if entry.id in read_book_ids %}<span class="badge read glyphicon glyphicon-ok"></span>{% endif %} |               {% if entry[2] == True %}<span class="badge read glyphicon glyphicon-ok"></span>{% endif %} | ||||||
|             </span> |             </span> | ||||||
|         </a> |         </a> | ||||||
|       </div> |       </div> | ||||||
|       <div class="meta"> |       <div class="meta"> | ||||||
|         <a href="{{ url_for('web.show_book', book_id=entry.id) }}"> |         <a href="{{ url_for('web.show_book', book_id=entry.Books.id) }}" {% if simple==false %}data-toggle="modal" data-target="#bookDetailsModal" data-remote="false"{% endif %}> | ||||||
|           <p title="{{ entry.title }}" class="title">{{entry.title|shortentitle}}</p> |           <p title="{{ entry.Books.title }}" class="title">{{entry.Books.title|shortentitle}}</p> | ||||||
|         </a> |         </a> | ||||||
|         <p class="author"> |         <p class="author"> | ||||||
|           {% for author in entry.ordered_authors %} |           {% for author in entry.Books.authors %} | ||||||
|             {% if loop.index > g.config_authors_max and g.config_authors_max != 0 %} |             {% if loop.index > g.config_authors_max and g.config_authors_max != 0 %} | ||||||
|               {% if not loop.first %} |               {% if not loop.first %} | ||||||
|                 <span class="author-hidden-divider">&</span> |                 <span class="author-hidden-divider">&</span> | ||||||
| @@ -63,23 +62,23 @@ | |||||||
|               <a class="author-name" href="{{url_for('web.books_list',  data='author', sort_param='stored', book_id=author.id) }}">{{author.name.replace('|',',')|shortentitle(30)}}</a> |               <a class="author-name" href="{{url_for('web.books_list',  data='author', sort_param='stored', book_id=author.id) }}">{{author.name.replace('|',',')|shortentitle(30)}}</a> | ||||||
|             {% endif %} |             {% endif %} | ||||||
|           {% endfor %} |           {% endfor %} | ||||||
|           {% for format in entry.data %} |           {% for format in entry.Books.data %} | ||||||
|             {% if format.format|lower in g.constants.EXTENSIONS_AUDIO %} |             {% if format.format|lower in g.constants.EXTENSIONS_AUDIO %} | ||||||
|             <span class="glyphicon glyphicon-music"></span> |             <span class="glyphicon glyphicon-music"></span> | ||||||
|             {% endif %} |             {% endif %} | ||||||
|           {% endfor %} |           {% endfor %} | ||||||
|         </p> |         </p> | ||||||
|         {% if entry.series.__len__() > 0 %} |         {% if entry.Books.series.__len__() > 0 %} | ||||||
|         <p class="series"> |         <p class="series"> | ||||||
|           <a href="{{url_for('web.books_list', data='series', sort_param='stored', book_id=entry.series[0].id )}}"> |           <a href="{{url_for('web.books_list', data='series', sort_param='stored', book_id=entry.Books.series[0].id )}}"> | ||||||
|             {{entry.series[0].name}} |             {{entry.Books.series[0].name}} | ||||||
|           </a> |           </a> | ||||||
|           ({{entry.series_index|formatseriesindex}}) |           ({{entry.Books.series_index|formatseriesindex}}) | ||||||
|         </p> |         </p> | ||||||
|         {% endif %} |         {% endif %} | ||||||
|         {% if entry.ratings.__len__() > 0 %} |         {% if entry.Books.ratings.__len__() > 0 %} | ||||||
|         <div class="rating"> |         <div class="rating"> | ||||||
|           {% for number in range((entry.ratings[0].rating/2)|int(2)) %} |           {% for number in range((entry.Books.ratings[0].rating/2)|int(2)) %} | ||||||
|           <span class="glyphicon glyphicon-star good"></span> |           <span class="glyphicon glyphicon-star good"></span> | ||||||
|           {% if loop.last and loop.index < 5 %} |           {% if loop.last and loop.index < 5 %} | ||||||
|           {% for numer in range(5 - loop.index) %} |           {% for numer in range(5 - loop.index) %} | ||||||
| @@ -92,7 +91,6 @@ | |||||||
|       </div> |       </div> | ||||||
|     </div> |     </div> | ||||||
|     {% endfor %} |     {% endfor %} | ||||||
|     {% endif %} |  | ||||||
|   </div> |   </div> | ||||||
| </div> | </div> | ||||||
|  |  | ||||||
| @@ -110,7 +108,7 @@ | |||||||
|       <div class="meta"> |       <div class="meta"> | ||||||
|         <p title="{{ entry.title }}" class="title">{{entry.title|shortentitle}}</p> |         <p title="{{ entry.title }}" class="title">{{entry.title|shortentitle}}</p> | ||||||
|         <p class="author"> |         <p class="author"> | ||||||
| 		  {% for author in entry.ordered_authors %} | 		  {% for author in entry.authors %} | ||||||
| 			{% if loop.index > g.config_authors_max and g.config_authors_max != 0 %} | 			{% if loop.index > g.config_authors_max and g.config_authors_max != 0 %} | ||||||
| 				<a class="author-name author-hidden" href="https://www.goodreads.com/author/show/{{ author.gid }}" target="_blank" rel="noopener">{{author.name.replace('|',',')}}</a> | 				<a class="author-name author-hidden" href="https://www.goodreads.com/author/show/{{ author.gid }}" target="_blank" rel="noopener">{{author.name.replace('|',',')}}</a> | ||||||
| 				{% if loop.last %} | 				{% if loop.last %} | ||||||
|   | |||||||
| @@ -1,65 +0,0 @@ | |||||||
| {% extends "layout.html" %} |  | ||||||
| {% block body %} |  | ||||||
| <div class="discover load-more"> |  | ||||||
|   <h2>{{title}}</h2> |  | ||||||
|   <div class="row display-flex"> |  | ||||||
|     {% for entry in entries %} |  | ||||||
|     <div class="col-sm-3 col-lg-2 col-xs-6 book"> |  | ||||||
|       <div class="cover"> |  | ||||||
|         {% if entry.has_cover is defined %} |  | ||||||
|           <a href="{{ url_for('web.show_book', book_id=entry.id) }}" {% if simple==false %}data-toggle="modal" data-target="#bookDetailsModal" data-remote="false"{% endif %}> |  | ||||||
|             <span class="img" title="{{entry.title}}"> |  | ||||||
|               <img src="{{ url_for('web.get_cover', book_id=entry.id) }}" alt="{{ entry.title }}" /> |  | ||||||
|               {% if entry.id in read_book_ids %}<span class="badge read glyphicon glyphicon-ok"></span>{% endif %} |  | ||||||
|             </span> |  | ||||||
|           </a> |  | ||||||
|         {% endif %} |  | ||||||
|       </div> |  | ||||||
|       <div class="meta"> |  | ||||||
|         <a href="{{ url_for('web.show_book', book_id=entry.id) }}" {% if simple==false %}data-toggle="modal" data-target="#bookDetailsModal" data-remote="false"{% endif %}> |  | ||||||
|           <p title="{{ entry.title }}" class="title">{{entry.title|shortentitle}}</p> |  | ||||||
|         </a> |  | ||||||
|         <p class="author"> |  | ||||||
|           {% for author in entry.ordered_authors %} |  | ||||||
|             {% if loop.index > g.config_authors_max and g.config_authors_max != 0 %} |  | ||||||
|               {% if not loop.first %} |  | ||||||
|                 <span class="author-hidden-divider">&</span> |  | ||||||
| 			  {% endif %} |  | ||||||
|               <a class="author-name author-hidden" href="{{url_for('web.books_list',  data='author', sort_param='stored', book_id=author.id) }}">{{author.name.replace('|',',')|shortentitle(30)}}</a> |  | ||||||
|               {% if loop.last %} |  | ||||||
|                 <a href="#" class="author-expand" data-authors-max="{{g.config_authors_max}}" data-collapse-caption="({{_('reduce')}})">(...)</a> |  | ||||||
|               {% endif %} |  | ||||||
|             {% else %} |  | ||||||
|               {% if not loop.first %} |  | ||||||
|                 <span>&</span> |  | ||||||
|               {% endif %} |  | ||||||
|               <a class="author-name" href="{{url_for('web.books_list',  data='author', sort_param='stored', book_id=author.id) }}">{{author.name.replace('|',',')|shortentitle(30)}}</a> |  | ||||||
|             {% endif %} |  | ||||||
|           {% endfor %} |  | ||||||
|         </p> |  | ||||||
|         {% if entry.series.__len__() > 0 %} |  | ||||||
|         <p class="series"> |  | ||||||
|           <a href="{{url_for('web.books_list', data='series', sort_param='stored', book_id=entry.series[0].id )}}"> |  | ||||||
|             {{entry.series[0].name}} |  | ||||||
|           </a> |  | ||||||
|           ({{entry.series_index|formatseriesindex}}) |  | ||||||
|         </p> |  | ||||||
|         {% endif %} |  | ||||||
|         {% if entry.ratings.__len__() > 0 %} |  | ||||||
|         <div class="rating"> |  | ||||||
|           {% for number in range((entry.ratings[0].rating/2)|int(2)) %} |  | ||||||
|             <span class="glyphicon glyphicon-star good"></span> |  | ||||||
|             {% if loop.last and loop.index < 5 %} |  | ||||||
|               {% for numer in range(5 - loop.index) %} |  | ||||||
|                 <span class="glyphicon glyphicon-star-empty"></span> |  | ||||||
|               {% endfor %} |  | ||||||
|             {% endif %} |  | ||||||
|           {% endfor %} |  | ||||||
|         </div> |  | ||||||
|         {% endif %} |  | ||||||
|       </div> |  | ||||||
|     </div> |  | ||||||
|     {% endfor %} |  | ||||||
|   </div> |  | ||||||
| </div> |  | ||||||
| {% endblock %} |  | ||||||
| @@ -40,35 +40,35 @@ | |||||||
|   {% if entries and entries[0] %} |   {% if entries and entries[0] %} | ||||||
|   {% for entry in entries %} |   {% for entry in entries %} | ||||||
|   <entry> |   <entry> | ||||||
|     <title>{{entry.title}}</title> |     <title>{{entry.Books.title}}</title> | ||||||
|     <id>urn:uuid:{{entry.uuid}}</id> |     <id>urn:uuid:{{entry.Books.uuid}}</id> | ||||||
|     <updated>{{entry.atom_timestamp}}</updated> |     <updated>{{entry.Books.atom_timestamp}}</updated> | ||||||
|     {% if entry.authors.__len__() > 0 %} |     {% if entry.Books.authors.__len__() > 0 %} | ||||||
|       <author> |       <author> | ||||||
|         <name>{{entry.authors[0].name}}</name> |         <name>{{entry.Books.authors[0].name}}</name> | ||||||
|       </author> |       </author> | ||||||
|     {% endif %} |     {% endif %} | ||||||
|     {% if entry.publishers.__len__() > 0 %} |     {% if entry.Books.publishers.__len__() > 0 %} | ||||||
|       <publisher> |       <publisher> | ||||||
|         <name>{{entry.publishers[0].name}}</name> |         <name>{{entry.Books.publishers[0].name}}</name> | ||||||
|       </publisher> |       </publisher> | ||||||
|     {% endif %} |     {% endif %} | ||||||
|     {% for lang in entry.languages %} |     {% for lang in entry.Books.languages %} | ||||||
|       <dcterms:language>{{lang.lang_code}}</dcterms:language> |       <dcterms:language>{{lang.lang_code}}</dcterms:language> | ||||||
|     {% endfor %} |     {% endfor %} | ||||||
|     {% for tag in entry.tags %} |     {% for tag in entry.Books.tags %} | ||||||
|     <category scheme="http://www.bisg.org/standards/bisac_subject/index.html" |     <category scheme="http://www.bisg.org/standards/bisac_subject/index.html" | ||||||
|               term="{{tag.name}}" |               term="{{tag.name}}" | ||||||
|               label="{{tag.name}}"/> |               label="{{tag.name}}"/> | ||||||
|     {% endfor %} |     {% endfor %} | ||||||
|     {% if entry.comments[0] %}<summary>{{entry.comments[0].text|striptags}}</summary>{% endif %} |     {% if entry.Books.comments[0] %}<summary>{{entry.Books.comments[0].text|striptags}}</summary>{% endif %} | ||||||
|     {% if entry.has_cover %} |     {% if entry.Books.has_cover %} | ||||||
|     <link type="image/jpeg" href="{{url_for('opds.feed_get_cover', book_id=entry.id)}}" rel="http://opds-spec.org/image"/> |     <link type="image/jpeg" href="{{url_for('opds.feed_get_cover', book_id=entry.Books.id)}}" rel="http://opds-spec.org/image"/> | ||||||
|     <link type="image/jpeg" href="{{url_for('opds.feed_get_cover', book_id=entry.id)}}" rel="http://opds-spec.org/image/thumbnail"/> |     <link type="image/jpeg" href="{{url_for('opds.feed_get_cover', book_id=entry.Books.id)}}" rel="http://opds-spec.org/image/thumbnail"/> | ||||||
|     {% endif %} |     {% endif %} | ||||||
|     {% for format in entry.data %} |     {% for format in entry.Books.data %} | ||||||
|     <link rel="http://opds-spec.org/acquisition" href="{{ url_for('opds.opds_download_link', book_id=entry.id, book_format=format.format|lower)}}" |     <link rel="http://opds-spec.org/acquisition" href="{{ url_for('opds.opds_download_link', book_id=entry.Books.id, book_format=format.format|lower)}}" | ||||||
|           length="{{format.uncompressed_size}}" mtime="{{entry.atom_timestamp}}" type="{{format.format|lower|mimetype}}"/> |           length="{{format.uncompressed_size}}" mtime="{{entry.Books.atom_timestamp}}" type="{{format.format|lower|mimetype}}"/> | ||||||
|     {% endfor %} |     {% endfor %} | ||||||
|   </entry> |   </entry> | ||||||
|   {% endfor %} |   {% endfor %} | ||||||
|   | |||||||
| @@ -1,25 +1,25 @@ | |||||||
| {% extends "layout.html" %} | {% extends "layout.html" %} | ||||||
| {% block body %} | {% block body %} | ||||||
| {% if g.user.show_detail_random() %} | {% if g.user.show_detail_random() and page != "discover" %} | ||||||
| <div class="discover random-books"> | <div class="discover random-books"> | ||||||
|   <h2 class="random-books">{{_('Discover (Random Books)')}}</h2> |   <h2 class="random-books">{{_('Discover (Random Books)')}}</h2> | ||||||
|   <div class="row display-flex"> |   <div class="row display-flex"> | ||||||
|    {% for entry in random %} |    {% for entry in random %} | ||||||
|     <div class="col-sm-3 col-lg-2 col-xs-6 book" id="books_rand"> |     <div class="col-sm-3 col-lg-2 col-xs-6 book" id="books_rand"> | ||||||
|       <div class="cover"> |       <div class="cover"> | ||||||
|           <a href="{{ url_for('web.show_book', book_id=entry.id) }}" {% if simple==false %}data-toggle="modal" data-target="#bookDetailsModal" data-remote="false"{% endif %}> |           <a href="{{ url_for('web.show_book', book_id=entry.Books.id) }}" {% if simple==false %}data-toggle="modal" data-target="#bookDetailsModal" data-remote="false"{% endif %}> | ||||||
|               <span class="img" title="{{ entry.title }}"> |               <span class="img" title="{{ entry.Books.title }}"> | ||||||
|                 <img src="{{ url_for('web.get_cover', book_id=entry.id) }}" alt="{{ entry.title }}" /> |                 <img src="{{ url_for('web.get_cover', book_id=entry.Books.id) }}" alt="{{ entry.Books.title }}" /> | ||||||
|                 {% if entry.id in read_book_ids %}<span class="badge read glyphicon glyphicon-ok"></span>{% endif %} |                 {% if entry[2] == True %}<span class="badge read glyphicon glyphicon-ok"></span>{% endif %} | ||||||
|               </span> |               </span> | ||||||
|           </a> |           </a> | ||||||
|       </div> |       </div> | ||||||
|       <div class="meta"> |       <div class="meta"> | ||||||
|         <a href="{{ url_for('web.show_book', book_id=entry.id) }}" {% if simple==false %}data-toggle="modal" data-target="#bookDetailsModal" data-remote="false"{% endif %}> |         <a href="{{ url_for('web.show_book', book_id=entry.Books.id) }}" {% if simple==false %}data-toggle="modal" data-target="#bookDetailsModal" data-remote="false"{% endif %}> | ||||||
|           <p title="{{entry.title}}" class="title">{{entry.title|shortentitle}}</p> |           <p title="{{entry.Books.title}}" class="title">{{entry.Books.title|shortentitle}}</p> | ||||||
|         </a> |         </a> | ||||||
|         <p class="author"> |         <p class="author"> | ||||||
|           {% for author in entry.ordered_authors %} |           {% for author in entry.Books.authors %} | ||||||
|             {% if loop.index > g.config_authors_max and g.config_authors_max != 0 %} |             {% if loop.index > g.config_authors_max and g.config_authors_max != 0 %} | ||||||
|               {% if not loop.first %} |               {% if not loop.first %} | ||||||
|                 <span class="author-hidden-divider">&</span> |                 <span class="author-hidden-divider">&</span> | ||||||
| @@ -36,17 +36,17 @@ | |||||||
|             {% endif %} |             {% endif %} | ||||||
|           {% endfor %} |           {% endfor %} | ||||||
|         </p> |         </p> | ||||||
|         {% if entry.series.__len__() > 0 %} |         {% if entry.Books.series.__len__() > 0 %} | ||||||
|         <p class="series"> |         <p class="series"> | ||||||
|           <a href="{{url_for('web.books_list', data='series', sort_param='stored', book_id=entry.series[0].id )}}"> |           <a href="{{url_for('web.books_list', data='series', sort_param='stored', book_id=entry.Books.series[0].id )}}"> | ||||||
|             {{entry.series[0].name}} |             {{entry.Books.series[0].name}} | ||||||
|           </a> |           </a> | ||||||
|           ({{entry.series_index|formatseriesindex}}) |           ({{entry.Books.series_index|formatseriesindex}}) | ||||||
|         </p> |         </p> | ||||||
|         {% endif %} |         {% endif %} | ||||||
|         {% if entry.ratings.__len__() > 0 %} |         {% if entry.Books.ratings.__len__() > 0 %} | ||||||
|         <div class="rating"> |         <div class="rating"> | ||||||
|           {% for number in range((entry.ratings[0].rating/2)|int(2)) %} |           {% for number in range((entry.Books.ratings[0].rating/2)|int(2)) %} | ||||||
|             <span class="glyphicon glyphicon-star good"></span> |             <span class="glyphicon glyphicon-star good"></span> | ||||||
|             {% if loop.last and loop.index < 5 %} |             {% if loop.last and loop.index < 5 %} | ||||||
|               {% for numer in range(5 - loop.index) %} |               {% for numer in range(5 - loop.index) %} | ||||||
| @@ -64,6 +64,7 @@ | |||||||
| {% endif %} | {% endif %} | ||||||
| <div class="discover load-more"> | <div class="discover load-more"> | ||||||
|   <h2 class="{{title}}">{{title}}</h2> |   <h2 class="{{title}}">{{title}}</h2> | ||||||
|  |    {% if page != 'discover' %} | ||||||
|     <div class="filterheader hidden-xs"> |     <div class="filterheader hidden-xs"> | ||||||
|     {% if page == 'hot' %} |     {% if page == 'hot' %} | ||||||
|       <a data-toggle="tooltip" title="{{_('Sort ascending according to download count')}}" id="hot_asc" class="btn btn-primary{% if order == "hotasc" %} active{% endif%}" href="{{url_for('web.books_list', data=page, book_id=id, sort_param='hotasc')}}"><span class="glyphicon glyphicon-sort-by-order"></span></a> |       <a data-toggle="tooltip" title="{{_('Sort ascending according to download count')}}" id="hot_asc" class="btn btn-primary{% if order == "hotasc" %} active{% endif%}" href="{{url_for('web.books_list', data=page, book_id=id, sort_param='hotasc')}}"><span class="glyphicon glyphicon-sort-by-order"></span></a> | ||||||
| @@ -83,25 +84,25 @@ | |||||||
|       {% endif %} |       {% endif %} | ||||||
|     {% endif %} |     {% endif %} | ||||||
|     </div> |     </div> | ||||||
|  |    {% endif %} | ||||||
|   <div class="row display-flex"> |   <div class="row display-flex"> | ||||||
|     {% if entries[0] %} |     {% if entries[0] %} | ||||||
|     {% for entry in entries %} |     {% for entry in entries %} | ||||||
|     <div class="col-sm-3 col-lg-2 col-xs-6 book" id="books"> |     <div class="col-sm-3 col-lg-2 col-xs-6 book" id="books"> | ||||||
|       <div class="cover"> |       <div class="cover"> | ||||||
|           <a href="{{ url_for('web.show_book', book_id=entry.id) }}" {% if simple==false %}data-toggle="modal" data-target="#bookDetailsModal" data-remote="false"{% endif %}> |           <a href="{{ url_for('web.show_book', book_id=entry.Books.id) }}" {% if simple==false %}data-toggle="modal" data-target="#bookDetailsModal" data-remote="false"{% endif %}> | ||||||
|             <span class="img" title="{{ entry.title }}"> |             <span class="img" title="{{ entry.Books.title }}"> | ||||||
|               <img src="{{ url_for('web.get_cover', book_id=entry.id) }}" alt="{{ entry.title }}"/> |               <img src="{{ url_for('web.get_cover', book_id=entry.Books.id) }}" alt="{{ entry.Books.title }}"/> | ||||||
|               {% if entry.id in read_book_ids %}<span class="badge read glyphicon glyphicon-ok"></span>{% endif %} |               {% if entry[2] == True %}<span class="badge read glyphicon glyphicon-ok"></span>{% endif %} | ||||||
|             </span> |             </span> | ||||||
|           </a> |           </a> | ||||||
|       </div> |       </div> | ||||||
|       <div class="meta"> |       <div class="meta"> | ||||||
|         <a href="{{ url_for('web.show_book', book_id=entry.id) }}" {% if simple==false %}data-toggle="modal" data-target="#bookDetailsModal" data-remote="false"{% endif %}> |         <a href="{{ url_for('web.show_book', book_id=entry.Books.id) }}" {% if simple==false %}data-toggle="modal" data-target="#bookDetailsModal" data-remote="false"{% endif %}> | ||||||
|           <p title="{{ entry.title }}" class="title">{{entry.title|shortentitle}}</p> |           <p title="{{ entry.Books.title }}" class="title">{{entry.Books.title|shortentitle}}</p> | ||||||
|         </a> |         </a> | ||||||
|         <p class="author"> |         <p class="author"> | ||||||
|           {% for author in entry.ordered_authors %} |           {% for author in entry.Books.authors %} | ||||||
|             {% if loop.index > g.config_authors_max and g.config_authors_max != 0 %} |             {% if loop.index > g.config_authors_max and g.config_authors_max != 0 %} | ||||||
|               {% if not loop.first %} |               {% if not loop.first %} | ||||||
|                 <span class="author-hidden-divider">&</span> |                 <span class="author-hidden-divider">&</span> | ||||||
| @@ -117,27 +118,27 @@ | |||||||
|               <a class="author-name" href="{{url_for('web.books_list', data='author', book_id=author.id, sort_param='stored') }}">{{author.name.replace('|',',')|shortentitle(30)}}</a> |               <a class="author-name" href="{{url_for('web.books_list', data='author', book_id=author.id, sort_param='stored') }}">{{author.name.replace('|',',')|shortentitle(30)}}</a> | ||||||
|             {% endif %} |             {% endif %} | ||||||
|           {% endfor %} |           {% endfor %} | ||||||
|           {% for format in entry.data %} |           {% for format in entry.Books.data %} | ||||||
|             {% if format.format|lower in g.constants.EXTENSIONS_AUDIO %} |             {% if format.format|lower in g.constants.EXTENSIONS_AUDIO %} | ||||||
|             <span class="glyphicon glyphicon-music"></span> |             <span class="glyphicon glyphicon-music"></span> | ||||||
|             {% endif %} |             {% endif %} | ||||||
|           {%endfor%} |           {%endfor%} | ||||||
|         </p> |         </p> | ||||||
|         {% if entry.series.__len__() > 0 %} |         {% if entry.Books.series.__len__() > 0 %} | ||||||
|         <p class="series"> |         <p class="series"> | ||||||
|         {% if page != "series" %} |         {% if page != "series" %} | ||||||
|           <a href="{{url_for('web.books_list', data='series', sort_param='stored', book_id=entry.series[0].id )}}"> |           <a href="{{url_for('web.books_list', data='series', sort_param='stored', book_id=entry.Books.series[0].id )}}"> | ||||||
|             {{entry.series[0].name}} |             {{entry.Books.series[0].name}} | ||||||
|           </a> |           </a> | ||||||
|         {% else %} |         {% else %} | ||||||
|             <span>{{entry.series[0].name}}</span> |             <span>{{entry.Books.series[0].name}}</span> | ||||||
|         {% endif %} |         {% endif %} | ||||||
|           ({{entry.series_index|formatseriesindex}}) |           ({{entry.Books.series_index|formatseriesindex}}) | ||||||
|         </p> |         </p> | ||||||
|         {% endif %} |         {% endif %} | ||||||
|         {% if entry.ratings.__len__() > 0 %} |         {% if entry.Books.ratings.__len__() > 0 %} | ||||||
|         <div class="rating"> |         <div class="rating"> | ||||||
|           {% for number in range((entry.ratings[0].rating/2)|int(2)) %} |           {% for number in range((entry.Books.ratings[0].rating/2)|int(2)) %} | ||||||
|             <span class="glyphicon glyphicon-star good"></span> |             <span class="glyphicon glyphicon-star good"></span> | ||||||
|             {% if loop.last and loop.index < 5 %} |             {% if loop.last and loop.index < 5 %} | ||||||
|               {% for numer in range(5 - loop.index) %} |               {% for numer in range(5 - loop.index) %} | ||||||
|   | |||||||
| @@ -46,7 +46,7 @@ | |||||||
|            <a href="{{ url_for('web.show_book', book_id=entry.Books.id) }}" {% if simple==false %}data-toggle="modal" data-target="#bookDetailsModal" data-remote="false"{% endif %}> |            <a href="{{ url_for('web.show_book', book_id=entry.Books.id) }}" {% if simple==false %}data-toggle="modal" data-target="#bookDetailsModal" data-remote="false"{% endif %}> | ||||||
|             <span class="img" title="{{entry.Books.title}}" > |             <span class="img" title="{{entry.Books.title}}" > | ||||||
|                 <img src="{{ url_for('web.get_cover', book_id=entry.Books.id) }}" alt="{{ entry.Books.title }}" /> |                 <img src="{{ url_for('web.get_cover', book_id=entry.Books.id) }}" alt="{{ entry.Books.title }}" /> | ||||||
|                 {% if entry.Books.id in read_book_ids %}<span class="badge read glyphicon glyphicon-ok"></span>{% endif %} |                 {% if entry[2] == True %}<span class="badge read glyphicon glyphicon-ok"></span>{% endif %} | ||||||
|             </span> |             </span> | ||||||
|           </a> |           </a> | ||||||
|         {% endif %} |         {% endif %} | ||||||
|   | |||||||
| @@ -32,19 +32,19 @@ | |||||||
|     {% for entry in entries %} |     {% for entry in entries %} | ||||||
|     <div class="col-sm-3 col-lg-2 col-xs-6 book"> |     <div class="col-sm-3 col-lg-2 col-xs-6 book"> | ||||||
|       <div class="cover"> |       <div class="cover"> | ||||||
|             <a href="{{ url_for('web.show_book', book_id=entry.id) }}" {% if simple==false %}data-toggle="modal" data-target="#bookDetailsModal" data-remote="false"{% endif %}> |             <a href="{{ url_for('web.show_book', book_id=entry.Books.id) }}" {% if simple==false %}data-toggle="modal" data-target="#bookDetailsModal" data-remote="false"{% endif %}> | ||||||
|               <span class="img" title="{{entry.title}}" > |               <span class="img" title="{{entry.Books.title}}" > | ||||||
|                 <img src="{{ url_for('web.get_cover', book_id=entry.id) }}" alt="{{ entry.title }}" /> |                 <img src="{{ url_for('web.get_cover', book_id=entry.Books.id) }}" alt="{{ entry.Books.title }}" /> | ||||||
|                 {% if entry.id in read_book_ids %}<span class="badge read glyphicon glyphicon-ok"></span>{% endif %} |                 {% if entry[2] == True %}<span class="badge read glyphicon glyphicon-ok"></span>{% endif %} | ||||||
|               </span> |               </span> | ||||||
|             </a> |             </a> | ||||||
|       </div> |       </div> | ||||||
|       <div class="meta"> |       <div class="meta"> | ||||||
|         <a href="{{ url_for('web.show_book', book_id=entry.id) }}" {% if simple==false %}data-toggle="modal" data-target="#bookDetailsModal" data-remote="false"{% endif %}> |         <a href="{{ url_for('web.show_book', book_id=entry.Books.id) }}" {% if simple==false %}data-toggle="modal" data-target="#bookDetailsModal" data-remote="false"{% endif %}> | ||||||
|           <p title="{{entry.title}}" class="title">{{entry.title|shortentitle}}</p> |           <p title="{{entry.Books.title}}" class="title">{{entry.Books.title|shortentitle}}</p> | ||||||
|         </a> |         </a> | ||||||
|         <p class="author"> |         <p class="author"> | ||||||
|           {% for author in entry.ordered_authors %} |           {% for author in entry.Books.authors %} | ||||||
|             {% if loop.index > g.config_authors_max and g.config_authors_max != 0 %} |             {% if loop.index > g.config_authors_max and g.config_authors_max != 0 %} | ||||||
|               {% if not loop.first %} |               {% if not loop.first %} | ||||||
|                 <span class="author-hidden-divider">&</span> |                 <span class="author-hidden-divider">&</span> | ||||||
| @@ -61,17 +61,17 @@ | |||||||
|             {% endif %} |             {% endif %} | ||||||
|           {% endfor %} |           {% endfor %} | ||||||
|         </p> |         </p> | ||||||
|         {% if entry.series.__len__() > 0 %} |         {% if entry.Books.series.__len__() > 0 %} | ||||||
|         <p class="series"> |         <p class="series"> | ||||||
|           <a href="{{url_for('web.books_list', data='series', sort_param='stored', book_id=entry.series[0].id )}}"> |           <a href="{{url_for('web.books_list', data='series', sort_param='stored', book_id=entry.Books.series[0].id )}}"> | ||||||
|             {{entry.series[0].name}} |             {{entry.Books.series[0].name}} | ||||||
|           </a> |           </a> | ||||||
|           ({{entry.series_index|formatseriesindex}}) |           ({{entry.Books.series_index|formatseriesindex}}) | ||||||
|         </p> |         </p> | ||||||
|         {% endif %} |         {% endif %} | ||||||
|         {% if entry.ratings.__len__() > 0 %} |         {% if entry.Books.ratings.__len__() > 0 %} | ||||||
|         <div class="rating"> |         <div class="rating"> | ||||||
|           {% for number in range((entry.ratings[0].rating/2)|int(2)) %} |           {% for number in range((entry.Books.ratings[0].rating/2)|int(2)) %} | ||||||
|             <span class="glyphicon glyphicon-star good"></span> |             <span class="glyphicon glyphicon-star good"></span> | ||||||
|             {% if loop.last and loop.index < 5 %} |             {% if loop.last and loop.index < 5 %} | ||||||
|               {% for numer in range(5 - loop.index) %} |               {% for numer in range(5 - loop.index) %} | ||||||
|   | |||||||
| @@ -35,31 +35,31 @@ | |||||||
|     <div class="col-sm-3 col-lg-2 col-xs-6 book"> |     <div class="col-sm-3 col-lg-2 col-xs-6 book"> | ||||||
|  |  | ||||||
|       <div class="meta"> |       <div class="meta"> | ||||||
|         <p title="{{entry.title}}" class="title">{{entry.title|shortentitle}}</p> |         <p title="{{entry.Books.title}}" class="title">{{entry.Books.title|shortentitle}}</p> | ||||||
|         <p class="author"> |         <p class="author"> | ||||||
|           {% for author in entry.ordered_authors %} |           {% for author in entry.Books.authors %} | ||||||
|             <a href="{{url_for('web.books_list',  data='author', sort_param='stored', book_id=author.id) }}">{{author.name.replace('|',',')}}</a> |             <a href="{{url_for('web.books_list',  data='author', sort_param='stored', book_id=author.id) }}">{{author.name.replace('|',',')}}</a> | ||||||
|             {% if not loop.last %} |             {% if not loop.last %} | ||||||
|               & |               & | ||||||
|             {% endif %} |             {% endif %} | ||||||
|           {% endfor %} |           {% endfor %} | ||||||
|         </p> |         </p> | ||||||
|         {% if entry.series.__len__() > 0 %} |         {% if entry.Books.series.__len__() > 0 %} | ||||||
|         <p class="series"> |         <p class="series"> | ||||||
|           <a href="{{url_for('web.books_list', data='series', sort_param='stored', book_id=entry.series[0].id )}}"> |           <a href="{{url_for('web.books_list', data='series', sort_param='stored', book_id=entry.Books.series[0].id )}}"> | ||||||
|             {{entry.series[0].name}} |             {{entry.Books.series[0].name}} | ||||||
|           </a> |           </a> | ||||||
|           ({{entry.series_index}}) |           ({{entry.Books.series_index}}) | ||||||
|         </p> |         </p> | ||||||
|         {% endif %} |         {% endif %} | ||||||
|       </div> |       </div> | ||||||
|  |  | ||||||
| 	  <div class="btn-group" role="group" aria-label="Download, send to Kindle, reading"> | 	  <div class="btn-group" role="group" aria-label="Download, send to Kindle, reading"> | ||||||
|           {% if g.user.role_download() %} |           {% if g.user.role_download() %} | ||||||
|             {% if entry.data|length %} |             {% if entry.Books.data|length %} | ||||||
|             <div class="btn-group" role="group"> |             <div class="btn-group" role="group"> | ||||||
|                 {% for format in entry.data %} |                 {% for format in entry.Books.data %} | ||||||
|                 <a href="{{ url_for('web.download_link', book_id=entry.id, book_format=format.format|lower, anyname=entry.id|string+'.'+format.format|lower) }}" id="btnGroupDrop{{entry.id}}{{format.format|lower}}" class="btn btn-primary" role="button"> |                 <a href="{{ url_for('web.download_link', book_id=entry.Books.id, book_format=format.format|lower, anyname=entry.Books.id|string+'.'+format.format|lower) }}" id="btnGroupDrop{{entry.Books.id}}{{format.format|lower}}" class="btn btn-primary" role="button"> | ||||||
|                   <span class="glyphicon glyphicon-download"></span>{{format.format}} ({{ format.uncompressed_size|filesizeformat }}) |                   <span class="glyphicon glyphicon-download"></span>{{format.format}} ({{ format.uncompressed_size|filesizeformat }}) | ||||||
|                 </a> |                 </a> | ||||||
|                 {% endfor %} |                 {% endfor %} | ||||||
|   | |||||||
							
								
								
									
										137
									
								
								cps/web.py
									
									
									
									
									
								
							
							
						
						
									
										137
									
								
								cps/web.py
									
									
									
									
									
								
							| @@ -85,7 +85,10 @@ except ImportError: | |||||||
| def add_security_headers(resp): | def add_security_headers(resp): | ||||||
|     csp = "default-src 'self'" |     csp = "default-src 'self'" | ||||||
|     csp += ''.join([' ' + host for host in config.config_trustedhosts.strip().split(',')]) |     csp += ''.join([' ' + host for host in config.config_trustedhosts.strip().split(',')]) | ||||||
|     csp += " 'unsafe-inline' 'unsafe-eval'; font-src 'self' data:; img-src 'self' data:" |     csp += " 'unsafe-inline' 'unsafe-eval'; font-src 'self' data:; img-src 'self' " | ||||||
|  |     if request.path.startswith("/author/") and config.config_use_goodreads: | ||||||
|  |         csp += "images.gr-assets.com i.gr-assets.com s.gr-assets.com" | ||||||
|  |     csp += " data:" | ||||||
|     resp.headers['Content-Security-Policy'] = csp |     resp.headers['Content-Security-Policy'] = csp | ||||||
|     if request.endpoint == "edit-book.show_edit_book" or config.config_use_google_drive: |     if request.endpoint == "edit-book.show_edit_book" or config.config_use_google_drive: | ||||||
|         resp.headers['Content-Security-Policy'] += " *" |         resp.headers['Content-Security-Policy'] += " *" | ||||||
| @@ -350,7 +353,7 @@ def render_books_list(data, sort_param, book_id, page): | |||||||
|     if data == "rated": |     if data == "rated": | ||||||
|         return render_rated_books(page, book_id, order=order) |         return render_rated_books(page, book_id, order=order) | ||||||
|     elif data == "discover": |     elif data == "discover": | ||||||
|         return render_discover_books(page, book_id) |         return render_discover_books(book_id) | ||||||
|     elif data == "unread": |     elif data == "unread": | ||||||
|         return render_read_books(page, False, order=order) |         return render_read_books(page, False, order=order) | ||||||
|     elif data == "read": |     elif data == "read": | ||||||
| @@ -386,7 +389,7 @@ def render_books_list(data, sort_param, book_id, page): | |||||||
|     else: |     else: | ||||||
|         website = data or "newest" |         website = data or "newest" | ||||||
|         entries, random, pagination = calibre_db.fill_indexpage(page, 0, db.Books, True, order[0], |         entries, random, pagination = calibre_db.fill_indexpage(page, 0, db.Books, True, order[0], | ||||||
|                                                                 False, 0, |                                                                 True, config.config_read_column, | ||||||
|                                                                 db.books_series_link, |                                                                 db.books_series_link, | ||||||
|                                                                 db.Books.id == db.books_series_link.c.book, |                                                                 db.Books.id == db.books_series_link.c.book, | ||||||
|                                                                 db.Series) |                                                                 db.Series) | ||||||
| @@ -400,7 +403,7 @@ def render_rated_books(page, book_id, order): | |||||||
|                                                                 db.Books, |                                                                 db.Books, | ||||||
|                                                                 db.Books.ratings.any(db.Ratings.rating > 9), |                                                                 db.Books.ratings.any(db.Ratings.rating > 9), | ||||||
|                                                                 order[0], |                                                                 order[0], | ||||||
|                                                                 False, 0, |                                                                 True, config.config_read_column, | ||||||
|                                                                 db.books_series_link, |                                                                 db.books_series_link, | ||||||
|                                                                 db.Books.id == db.books_series_link.c.book, |                                                                 db.Books.id == db.books_series_link.c.book, | ||||||
|                                                                 db.Series) |                                                                 db.Series) | ||||||
| @@ -411,11 +414,13 @@ def render_rated_books(page, book_id, order): | |||||||
|         abort(404) |         abort(404) | ||||||
|  |  | ||||||
|  |  | ||||||
| def render_discover_books(page, book_id): | def render_discover_books(book_id): | ||||||
|     if current_user.check_visibility(constants.SIDEBAR_RANDOM): |     if current_user.check_visibility(constants.SIDEBAR_RANDOM): | ||||||
|         entries, __, pagination = calibre_db.fill_indexpage(page, 0, db.Books, True, [func.randomblob(2)]) |         entries, __, ___ = calibre_db.fill_indexpage(1, 0, db.Books, True, [func.randomblob(2)], | ||||||
|  |                                                             join_archive_read=True, | ||||||
|  |                                                             config_read_column=config.config_read_column) | ||||||
|         pagination = Pagination(1, config.config_books_per_page, config.config_books_per_page) |         pagination = Pagination(1, config.config_books_per_page, config.config_books_per_page) | ||||||
|         return render_title_template('discover.html', entries=entries, pagination=pagination, id=book_id, |         return render_title_template('index.html', random=false(), entries=entries, pagination=pagination, id=book_id, | ||||||
|                                      title=_(u"Discover (Random Books)"), page="discover") |                                      title=_(u"Discover (Random Books)"), page="discover") | ||||||
|     else: |     else: | ||||||
|         abort(404) |         abort(404) | ||||||
| @@ -429,18 +434,22 @@ def render_hot_books(page, order): | |||||||
|             #        order[0][0].compare(func.count(ub.Downloads.book_id).asc())): |             #        order[0][0].compare(func.count(ub.Downloads.book_id).asc())): | ||||||
|             order = [func.count(ub.Downloads.book_id).desc()], 'hotdesc' |             order = [func.count(ub.Downloads.book_id).desc()], 'hotdesc' | ||||||
|         if current_user.show_detail_random(): |         if current_user.show_detail_random(): | ||||||
|             random = calibre_db.session.query(db.Books).filter(calibre_db.common_filters()) \ |             random_query = calibre_db.generate_linked_query(config.config_read_column, db.Books) | ||||||
|                 .order_by(func.random()).limit(config.config_random_books) |             random = (random_query.filter(calibre_db.common_filters()) | ||||||
|  |                      .order_by(func.random()) | ||||||
|  |                      .limit(config.config_random_books).all()) | ||||||
|         else: |         else: | ||||||
|             random = false() |             random = false() | ||||||
|  |  | ||||||
|         off = int(int(config.config_books_per_page) * (page - 1)) |         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) |             .order_by(*order[0]).group_by(ub.Downloads.book_id) | ||||||
|         hot_books = all_books.offset(off).limit(config.config_books_per_page) |         hot_books = all_books.offset(off).limit(config.config_books_per_page) | ||||||
|         entries = list() |         entries = list() | ||||||
|         for book in hot_books: |         for book in hot_books: | ||||||
|             download_book = calibre_db.session.query(db.Books).filter(calibre_db.common_filters()).filter( |             query = calibre_db.generate_linked_query(config.config_read_column, db.Books) | ||||||
|                 db.Books.id == book.Downloads.book_id).first() |             download_book = query.filter(calibre_db.common_filters()).filter( | ||||||
|  |                 book.Downloads.book_id == db.Books.id).first() | ||||||
|             if download_book: |             if download_book: | ||||||
|                 entries.append(download_book) |                 entries.append(download_book) | ||||||
|             else: |             else: | ||||||
| @@ -459,26 +468,20 @@ def render_downloaded_books(page, order, user_id): | |||||||
|     else: |     else: | ||||||
|         user_id = current_user.id |         user_id = current_user.id | ||||||
|     if current_user.check_visibility(constants.SIDEBAR_DOWNLOAD): |     if current_user.check_visibility(constants.SIDEBAR_DOWNLOAD): | ||||||
|         if current_user.show_detail_random(): |         entries, random, pagination = calibre_db.fill_indexpage(page, | ||||||
|             random = calibre_db.session.query(db.Books).filter(calibre_db.common_filters()) \ |  | ||||||
|                 .order_by(func.random()).limit(config.config_random_books) |  | ||||||
|         else: |  | ||||||
|             random = false() |  | ||||||
|  |  | ||||||
|         entries, __, pagination = calibre_db.fill_indexpage(page, |  | ||||||
|                                                             0, |                                                             0, | ||||||
|                                                             db.Books, |                                                             db.Books, | ||||||
|                                                             ub.Downloads.user_id == user_id, |                                                             ub.Downloads.user_id == user_id, | ||||||
|                                                             order[0], |                                                             order[0], | ||||||
|                                                             False, 0, |                                                             True, config.config_read_column, | ||||||
|                                                             db.books_series_link, |                                                             db.books_series_link, | ||||||
|                                                             db.Books.id == db.books_series_link.c.book, |                                                             db.Books.id == db.books_series_link.c.book, | ||||||
|                                                             db.Series, |                                                             db.Series, | ||||||
|                                                             ub.Downloads, db.Books.id == ub.Downloads.book_id) |                                                             ub.Downloads, db.Books.id == ub.Downloads.book_id) | ||||||
|         for book in entries: |         for book in entries: | ||||||
|             if not calibre_db.session.query(db.Books).\ |             if not (calibre_db.session.query(db.Books).filter(calibre_db.common_filters()) | ||||||
|                                             filter(calibre_db.common_filters()).filter(db.Books.id == book.id).first(): |                     .filter(db.Books.id == book.Books.id).first()): | ||||||
|                 ub.delete_download(book.id) |                 ub.delete_download(book.Books.id) | ||||||
|         user = ub.session.query(ub.User).filter(ub.User.id == user_id).first() |         user = ub.session.query(ub.User).filter(ub.User.id == user_id).first() | ||||||
|         return render_title_template('index.html', |         return render_title_template('index.html', | ||||||
|                                      random=random, |                                      random=random, | ||||||
| @@ -497,9 +500,9 @@ def render_author_books(page, author_id, order): | |||||||
|                                                         db.Books, |                                                         db.Books, | ||||||
|                                                         db.Books.authors.any(db.Authors.id == author_id), |                                                         db.Books.authors.any(db.Authors.id == author_id), | ||||||
|                                                         [order[0][0], db.Series.name, db.Books.series_index], |                                                         [order[0][0], db.Series.name, db.Books.series_index], | ||||||
|                                                         False, 0, |                                                         True, config.config_read_column, | ||||||
|                                                         db.books_series_link, |                                                         db.books_series_link, | ||||||
|                                                         db.Books.id == db.books_series_link.c.book, |                                                         db.books_series_link.c.book == db.Books.id, | ||||||
|                                                         db.Series) |                                                         db.Series) | ||||||
|     if entries is None or not len(entries): |     if entries is None or not len(entries): | ||||||
|         flash(_(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"), | ||||||
| @@ -515,7 +518,8 @@ def render_author_books(page, author_id, order): | |||||||
|     other_books = [] |     other_books = [] | ||||||
|     if services.goodreads_support and config.config_use_goodreads: |     if services.goodreads_support and config.config_use_goodreads: | ||||||
|         author_info = services.goodreads_support.get_author_info(author_name) |         author_info = services.goodreads_support.get_author_info(author_name) | ||||||
|         other_books = services.goodreads_support.get_other_books(author_info, entries) |         book_entries = [entry.Books for entry in entries] | ||||||
|  |         other_books = services.goodreads_support.get_other_books(author_info, book_entries) | ||||||
|     return render_title_template('author.html', entries=entries, pagination=pagination, id=author_id, |     return render_title_template('author.html', entries=entries, pagination=pagination, id=author_id, | ||||||
|                                  title=_(u"Author: %(name)s", name=author_name), author=author_info, |                                  title=_(u"Author: %(name)s", name=author_name), author=author_info, | ||||||
|                                  other_books=other_books, page="author", order=order[1]) |                                  other_books=other_books, page="author", order=order[1]) | ||||||
| @@ -528,7 +532,7 @@ def render_publisher_books(page, book_id, order): | |||||||
|                                                                 db.Books, |                                                                 db.Books, | ||||||
|                                                                 db.Books.publishers.any(db.Publishers.id == book_id), |                                                                 db.Books.publishers.any(db.Publishers.id == book_id), | ||||||
|                                                                 [db.Series.name, order[0][0], db.Books.series_index], |                                                                 [db.Series.name, order[0][0], db.Books.series_index], | ||||||
|                                                                 False, 0, |                                                                 True, config.config_read_column, | ||||||
|                                                                 db.books_series_link, |                                                                 db.books_series_link, | ||||||
|                                                                 db.Books.id == db.books_series_link.c.book, |                                                                 db.Books.id == db.books_series_link.c.book, | ||||||
|                                                                 db.Series) |                                                                 db.Series) | ||||||
| @@ -546,7 +550,8 @@ def render_series_books(page, book_id, order): | |||||||
|         entries, random, pagination = calibre_db.fill_indexpage(page, 0, |         entries, random, pagination = calibre_db.fill_indexpage(page, 0, | ||||||
|                                                                 db.Books, |                                                                 db.Books, | ||||||
|                                                                 db.Books.series.any(db.Series.id == book_id), |                                                                 db.Books.series.any(db.Series.id == book_id), | ||||||
|                                                                 [order[0][0]]) |                                                                 [order[0][0]], | ||||||
|  |                                                                 True, config.config_read_column) | ||||||
|         return render_title_template('index.html', random=random, pagination=pagination, entries=entries, id=book_id, |         return render_title_template('index.html', random=random, pagination=pagination, entries=entries, id=book_id, | ||||||
|                                      title=_(u"Series: %(serie)s", serie=name.name), page="series", order=order[1]) |                                      title=_(u"Series: %(serie)s", serie=name.name), page="series", order=order[1]) | ||||||
|     else: |     else: | ||||||
| @@ -558,7 +563,8 @@ def render_ratings_books(page, book_id, order): | |||||||
|     entries, random, pagination = calibre_db.fill_indexpage(page, 0, |     entries, random, pagination = calibre_db.fill_indexpage(page, 0, | ||||||
|                                                             db.Books, |                                                             db.Books, | ||||||
|                                                             db.Books.ratings.any(db.Ratings.id == book_id), |                                                             db.Books.ratings.any(db.Ratings.id == book_id), | ||||||
|                                                             [order[0][0]]) |                                                             [order[0][0]], | ||||||
|  |                                                             True, config.config_read_column) | ||||||
|     if name and name.rating <= 10: |     if name and name.rating <= 10: | ||||||
|         return render_title_template('index.html', random=random, pagination=pagination, entries=entries, id=book_id, |         return render_title_template('index.html', random=random, pagination=pagination, entries=entries, id=book_id, | ||||||
|                                      title=_(u"Rating: %(rating)s stars", rating=int(name.rating / 2)), |                                      title=_(u"Rating: %(rating)s stars", rating=int(name.rating / 2)), | ||||||
| @@ -574,7 +580,8 @@ def render_formats_books(page, book_id, order): | |||||||
|         entries, random, pagination = calibre_db.fill_indexpage(page, 0, |         entries, random, pagination = calibre_db.fill_indexpage(page, 0, | ||||||
|                                                                 db.Books, |                                                                 db.Books, | ||||||
|                                                                 db.Books.data.any(db.Data.format == book_id.upper()), |                                                                 db.Books.data.any(db.Data.format == book_id.upper()), | ||||||
|                                                                 [order[0][0]]) |                                                                 [order[0][0]], | ||||||
|  |                                                                 True, config.config_read_column) | ||||||
|         return render_title_template('index.html', random=random, pagination=pagination, entries=entries, id=book_id, |         return render_title_template('index.html', random=random, pagination=pagination, entries=entries, id=book_id, | ||||||
|                                      title=_(u"File format: %(format)s", format=name.format), |                                      title=_(u"File format: %(format)s", format=name.format), | ||||||
|                                      page="formats", |                                      page="formats", | ||||||
| @@ -590,7 +597,7 @@ def render_category_books(page, book_id, order): | |||||||
|                                                                 db.Books, |                                                                 db.Books, | ||||||
|                                                                 db.Books.tags.any(db.Tags.id == book_id), |                                                                 db.Books.tags.any(db.Tags.id == book_id), | ||||||
|                                                                 [order[0][0], db.Series.name, db.Books.series_index], |                                                                 [order[0][0], db.Series.name, db.Books.series_index], | ||||||
|                                                                 False, 0, |                                                                 True, config.config_read_column, | ||||||
|                                                                 db.books_series_link, |                                                                 db.books_series_link, | ||||||
|                                                                 db.Books.id == db.books_series_link.c.book, |                                                                 db.Books.id == db.books_series_link.c.book, | ||||||
|                                                                 db.Series) |                                                                 db.Series) | ||||||
| @@ -609,7 +616,8 @@ def render_language_books(page, name, order): | |||||||
|     entries, random, pagination = calibre_db.fill_indexpage(page, 0, |     entries, random, pagination = calibre_db.fill_indexpage(page, 0, | ||||||
|                                                             db.Books, |                                                             db.Books, | ||||||
|                                                             db.Books.languages.any(db.Languages.lang_code == name), |                                                             db.Books.languages.any(db.Languages.lang_code == name), | ||||||
|                                                             [order[0][0]]) |                                                             [order[0][0]], | ||||||
|  |                                                             True, config.config_read_column) | ||||||
|     return render_title_template('index.html', random=random, entries=entries, pagination=pagination, id=name, |     return render_title_template('index.html', random=random, entries=entries, pagination=pagination, id=name, | ||||||
|                                  title=_(u"Language: %(name)s", name=lang_name), page="language", order=order[1]) |                                  title=_(u"Language: %(name)s", name=lang_name), page="language", order=order[1]) | ||||||
|  |  | ||||||
| @@ -622,30 +630,12 @@ def render_read_books(page, are_read, as_xml=False, order=None): | |||||||
|                              ub.ReadBook.read_status == ub.ReadBook.STATUS_FINISHED) |                              ub.ReadBook.read_status == ub.ReadBook.STATUS_FINISHED) | ||||||
|         else: |         else: | ||||||
|             db_filter = coalesce(ub.ReadBook.read_status, 0) != ub.ReadBook.STATUS_FINISHED |             db_filter = coalesce(ub.ReadBook.read_status, 0) != ub.ReadBook.STATUS_FINISHED | ||||||
|         entries, random, pagination = calibre_db.fill_indexpage(page, 0, |  | ||||||
|                                                                 db.Books, |  | ||||||
|                                                                 db_filter, |  | ||||||
|                                                                 sort_param, |  | ||||||
|                                                                 False, 0, |  | ||||||
|                                                                 db.books_series_link, |  | ||||||
|                                                                 db.Books.id == db.books_series_link.c.book, |  | ||||||
|                                                                 db.Series, |  | ||||||
|                                                                 ub.ReadBook, db.Books.id == ub.ReadBook.book_id) |  | ||||||
|     else: |     else: | ||||||
|         try: |         try: | ||||||
|             if are_read: |             if are_read: | ||||||
|                 db_filter = db.cc_classes[config.config_read_column].value == True |                 db_filter = db.cc_classes[config.config_read_column].value == True | ||||||
|             else: |             else: | ||||||
|                 db_filter = coalesce(db.cc_classes[config.config_read_column].value, False) != True |                 db_filter = coalesce(db.cc_classes[config.config_read_column].value, False) != True | ||||||
|             entries, random, pagination = calibre_db.fill_indexpage(page, 0, |  | ||||||
|                                                                     db.Books, |  | ||||||
|                                                                     db_filter, |  | ||||||
|                                                                     sort_param, |  | ||||||
|                                                                     False, 0, |  | ||||||
|                                                                     db.books_series_link, |  | ||||||
|                                                                     db.Books.id == db.books_series_link.c.book, |  | ||||||
|                                                                     db.Series, |  | ||||||
|                                                                     db.cc_classes[config.config_read_column]) |  | ||||||
|         except (KeyError, AttributeError, IndexError): |         except (KeyError, AttributeError, IndexError): | ||||||
|             log.error("Custom Column No.{} is not existing in calibre database".format(config.config_read_column)) |             log.error("Custom Column No.{} is not existing in calibre database".format(config.config_read_column)) | ||||||
|             if not as_xml: |             if not as_xml: | ||||||
| @@ -655,6 +645,15 @@ def render_read_books(page, are_read, as_xml=False, order=None): | |||||||
|                 return redirect(url_for("web.index")) |                 return redirect(url_for("web.index")) | ||||||
|             return []  # ToDo: Handle error Case for opds |             return []  # ToDo: Handle error Case for opds | ||||||
|  |  | ||||||
|  |     entries, random, pagination = calibre_db.fill_indexpage(page, 0, | ||||||
|  |                                                             db.Books, | ||||||
|  |                                                             db_filter, | ||||||
|  |                                                             sort_param, | ||||||
|  |                                                             True, config.config_read_column, | ||||||
|  |                                                             db.books_series_link, | ||||||
|  |                                                             db.Books.id == db.books_series_link.c.book, | ||||||
|  |                                                             db.Series) | ||||||
|  |  | ||||||
|     if as_xml: |     if as_xml: | ||||||
|         return entries, pagination |         return entries, pagination | ||||||
|     else: |     else: | ||||||
| @@ -683,7 +682,7 @@ def render_archived_books(page, sort_param): | |||||||
|                                                                                 archived_filter, |                                                                                 archived_filter, | ||||||
|                                                                                 order, |                                                                                 order, | ||||||
|                                                                                 True, |                                                                                 True, | ||||||
|                                                                                 False, 0) |                                                                                 True, config.config_read_column) | ||||||
|  |  | ||||||
|     name = _(u'Archived Books') + ' (' + str(len(archived_book_ids)) + ')' |     name = _(u'Archived Books') + ' (' + str(len(archived_book_ids)) + ')' | ||||||
|     page_name = "archived" |     page_name = "archived" | ||||||
| @@ -723,7 +722,7 @@ def render_prepare_search_form(cc): | |||||||
|  |  | ||||||
|  |  | ||||||
| def render_search_results(term, offset=None, order=None, limit=None): | def render_search_results(term, offset=None, order=None, limit=None): | ||||||
|     join = db.books_series_link, db.Books.id == db.books_series_link.c.book, db.Series |     join = db.books_series_link, db.books_series_link.c.book == db.Books.id, db.Series | ||||||
|     entries, result_count, pagination = calibre_db.get_search_results(term, |     entries, result_count, pagination = calibre_db.get_search_results(term, | ||||||
|                                                                       offset, |                                                                       offset, | ||||||
|                                                                       order, |                                                                       order, | ||||||
| @@ -813,27 +812,8 @@ def list_books(): | |||||||
|             books = calibre_db.search_query(search_param, config.config_read_column).all() |             books = calibre_db.search_query(search_param, config.config_read_column).all() | ||||||
|             filtered_count = len(books) |             filtered_count = len(books) | ||||||
|         else: |         else: | ||||||
|             if not config.config_read_column: |             query = calibre_db.generate_linked_query(config.config_read_column, db.Books) | ||||||
|                 books = (calibre_db.session.query(db.Books, ub.ReadBook.read_status, ub.ArchivedBook.is_archived) |             books = query.filter(calibre_db.common_filters(allow_show_archived=True)).all() | ||||||
|                          .select_from(db.Books) |  | ||||||
|                          .outerjoin(ub.ReadBook, |  | ||||||
|                                     and_(ub.ReadBook.user_id == int(current_user.id), |  | ||||||
|                                          ub.ReadBook.book_id == db.Books.id))) |  | ||||||
|             else: |  | ||||||
|                 read_column = "" |  | ||||||
|                 try: |  | ||||||
|                     read_column = db.cc_classes[config.config_read_column] |  | ||||||
|                     books = (calibre_db.session.query(db.Books, read_column.value, ub.ArchivedBook.is_archived) |  | ||||||
|                              .select_from(db.Books) |  | ||||||
|                              .outerjoin(read_column, read_column.book == db.Books.id)) |  | ||||||
|                 except (KeyError, AttributeError, IndexError): |  | ||||||
|                     log.error( |  | ||||||
|                         "Custom Column No.{} is not existing in calibre database".format(config.config_read_column)) |  | ||||||
|                     # 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)) |  | ||||||
|                      .filter(calibre_db.common_filters(allow_show_archived=True)).all()) |  | ||||||
|         entries = calibre_db.get_checkbox_sorted(books, state, off, limit, order, True) |         entries = calibre_db.get_checkbox_sorted(books, state, off, limit, order, True) | ||||||
|     elif search_param: |     elif search_param: | ||||||
|         entries, filtered_count, __ = calibre_db.get_search_results(search_param, |         entries, filtered_count, __ = calibre_db.get_search_results(search_param, | ||||||
| @@ -856,8 +836,8 @@ def list_books(): | |||||||
|     result = list() |     result = list() | ||||||
|     for entry in entries: |     for entry in entries: | ||||||
|         val = entry[0] |         val = entry[0] | ||||||
|         val.read_status = entry[1] == ub.ReadBook.STATUS_FINISHED |         val.is_archived = entry[1] is True | ||||||
|         val.is_archived = entry[2] is True |         val.read_status = entry[2] == ub.ReadBook.STATUS_FINISHED | ||||||
|         for lang_index in range(0, len(val.languages)): |         for lang_index in range(0, len(val.languages)): | ||||||
|             val.languages[lang_index].language_name = isoLanguages.get_language_name(get_locale(), val.languages[ |             val.languages[lang_index].language_name = isoLanguages.get_language_name(get_locale(), val.languages[ | ||||||
|                 lang_index].lang_code) |                 lang_index].lang_code) | ||||||
| @@ -1254,13 +1234,14 @@ def render_adv_search_results(term, offset=None, order=None, limit=None): | |||||||
|  |  | ||||||
|     cc = get_cc_columns(filter_config_custom_read=True) |     cc = get_cc_columns(filter_config_custom_read=True) | ||||||
|     calibre_db.session.connection().connection.connection.create_function("lower", 1, db.lcase) |     calibre_db.session.connection().connection.connection.create_function("lower", 1, db.lcase) | ||||||
|     if not config.config_read_column: |     query = calibre_db.generate_linked_query(config.config_read_column, db.Books) | ||||||
|  |     '''if not config.config_read_column: | ||||||
|         query = (calibre_db.session.query(db.Books, ub.ArchivedBook.is_archived, ub.ReadBook).select_from(db.Books) |         query = (calibre_db.session.query(db.Books, ub.ArchivedBook.is_archived, ub.ReadBook).select_from(db.Books) | ||||||
|                  .outerjoin(ub.ReadBook, and_(db.Books.id == ub.ReadBook.book_id, |                  .outerjoin(ub.ReadBook, and_(db.Books.id == ub.ReadBook.book_id, | ||||||
|                                               int(current_user.id) == ub.ReadBook.user_id))) |                                               int(current_user.id) == ub.ReadBook.user_id))) | ||||||
|     else: |     else: | ||||||
|         try: |         try: | ||||||
|             read_column = cc[config.config_read_column] |             read_column = db.cc_classes[config.config_read_column] | ||||||
|             query = (calibre_db.session.query(db.Books, ub.ArchivedBook.is_archived, read_column.value) |             query = (calibre_db.session.query(db.Books, ub.ArchivedBook.is_archived, read_column.value) | ||||||
|                     .select_from(db.Books) |                     .select_from(db.Books) | ||||||
|                     .outerjoin(read_column, read_column.book == db.Books.id)) |                     .outerjoin(read_column, read_column.book == db.Books.id)) | ||||||
| @@ -1269,9 +1250,9 @@ def render_adv_search_results(term, offset=None, order=None, limit=None): | |||||||
|             # Skip linking read column |             # Skip linking read column | ||||||
|             query = calibre_db.session.query(db.Books, ub.ArchivedBook.is_archived, None) |             query = calibre_db.session.query(db.Books, ub.ArchivedBook.is_archived, None) | ||||||
|     query = query.outerjoin(ub.ArchivedBook, and_(db.Books.id == ub.ArchivedBook.book_id, |     query = query.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))''' | ||||||
|  |  | ||||||
|     q = query.outerjoin(db.books_series_link, db.Books.id == db.books_series_link.c.book) \ |     q = query.outerjoin(db.books_series_link, db.books_series_link.c.book == db.Books.id) \ | ||||||
|         .outerjoin(db.Series) \ |         .outerjoin(db.Series) \ | ||||||
|         .filter(calibre_db.common_filters(True)) |         .filter(calibre_db.common_filters(True)) | ||||||
|  |  | ||||||
|   | |||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
		Reference in New Issue
	
	Block a user
	 Ozzie Isaacs
					Ozzie Isaacs