mirror of
				https://github.com/janeczku/calibre-web
				synced 2025-10-31 07:13:02 +00:00 
			
		
		
		
	| @@ -47,10 +47,9 @@ def process(tmp_file_path, original_file_name, original_file_extension): | ||||
|         if ".EPUB" == original_file_extension.upper() and use_epub_meta is True: | ||||
|             return epub.get_epub_info(tmp_file_path, original_file_name, original_file_extension) | ||||
|         if ".FB2" == original_file_extension.upper() and use_fb2_meta is True: | ||||
|             return fb2.get_fb2_info(tmp_file_path, original_file_name, original_file_extension) | ||||
|             return fb2.get_fb2_info(tmp_file_path, original_file_extension) | ||||
|     except Exception, e: | ||||
|         logger.warning('cannot parse metadata, using default: %s', e) | ||||
|  | ||||
|     return default_meta(tmp_file_path, original_file_name, original_file_extension) | ||||
|  | ||||
|  | ||||
| @@ -59,7 +58,7 @@ def default_meta(tmp_file_path, original_file_name, original_file_extension): | ||||
|         file_path=tmp_file_path, | ||||
|         extension=original_file_extension, | ||||
|         title=original_file_name, | ||||
|         author="Unknown", | ||||
|         author=u"Unknown", | ||||
|         cover=None, | ||||
|         description="", | ||||
|         tags="", | ||||
| @@ -76,11 +75,11 @@ def pdf_meta(tmp_file_path, original_file_name, original_file_extension): | ||||
|         doc_info = None | ||||
|  | ||||
|     if doc_info is not None: | ||||
|         author = doc_info.author if doc_info.author is not None else "Unknown" | ||||
|         author = doc_info.author if doc_info.author is not None else u"Unknown" | ||||
|         title = doc_info.title if doc_info.title is not None else original_file_name | ||||
|         subject = doc_info.subject | ||||
|     else: | ||||
|         author = "Unknown" | ||||
|         author = u"Unknown" | ||||
|         title = original_file_name | ||||
|         subject = "" | ||||
|     return uploader.BookMeta( | ||||
| @@ -100,7 +99,7 @@ def pdf_preview(tmp_file_path, tmp_dir): | ||||
|         return None | ||||
|     else: | ||||
|         cover_file_name = os.path.splitext(tmp_file_path)[0] + ".cover.jpg" | ||||
|         with Image(filename=tmp_file_path + "[0]", resolution=150) as img: | ||||
|         with Image(filename=tmp_file_path +"[0]", resolution=150) as img: | ||||
|             img.compression_quality = 88 | ||||
|             img.save(filename=os.path.join(tmp_dir, cover_file_name)) | ||||
|         return cover_file_name | ||||
| @@ -109,9 +108,9 @@ def get_versions(): | ||||
|     if not use_generic_pdf_cover: | ||||
|         IVersion=ImageVersion.MAGICK_VERSION | ||||
|     else: | ||||
|         IVersion=_('not installed') | ||||
|         IVersion=_(u'not installed') | ||||
|     if use_pdf_meta: | ||||
|         PVersion=PyPdfVersion | ||||
|     else: | ||||
|         PVersion=_('not installed') | ||||
|         PVersion=_(u'not installed') | ||||
|     return {'ImageVersion':IVersion,'PyPdfVersion':PVersion} | ||||
| @@ -21,7 +21,6 @@ engine = None | ||||
| # user defined sort function for calibre databases (Series, etc.) | ||||
| def title_sort(title): | ||||
|     # calibre sort stuff | ||||
|     # config=Config() | ||||
|     title_pat = re.compile(config.config_title_regex, re.IGNORECASE) | ||||
|     match = title_pat.search(title) | ||||
|     if match: | ||||
|   | ||||
| @@ -59,8 +59,8 @@ def get_epub_info(tmp_file_path, original_file_name, original_file_extension): | ||||
|     return uploader.BookMeta( | ||||
|         file_path=tmp_file_path, | ||||
|         extension=original_file_extension, | ||||
|         title=title, | ||||
|         author=epub_metadata['creator'], | ||||
|         title=title.encode('utf-8').decode('utf-8'), | ||||
|         author=epub_metadata['creator'].encode('utf-8').decode('utf-8'), | ||||
|         cover=coverfile, | ||||
|         description=epub_metadata['description'], | ||||
|         tags="", | ||||
|   | ||||
							
								
								
									
										43
									
								
								cps/fb2.py
									
									
									
									
									
								
							
							
						
						
									
										43
									
								
								cps/fb2.py
									
									
									
									
									
								
							| @@ -4,9 +4,10 @@ | ||||
| from lxml import etree | ||||
| import os | ||||
| import uploader | ||||
| import StringIO | ||||
|  | ||||
| # ToDo: Check usage of original_file_name | ||||
| def get_fb2_info(tmp_file_path, original_file_name, original_file_extension): | ||||
| def get_fb2_info(tmp_file_path, original_file_extension): | ||||
|  | ||||
|     ns = { | ||||
|         'fb': 'http://www.gribuser.ru/xml/fictionbook/2.0', | ||||
| @@ -19,19 +20,43 @@ def get_fb2_info(tmp_file_path, original_file_name, original_file_extension): | ||||
|     authors = tree.xpath('/fb:FictionBook/fb:description/fb:title-info/fb:author', namespaces=ns) | ||||
|  | ||||
|     def get_author(element): | ||||
|         return element.xpath('fb:first-name/text()', namespaces=ns)[0] + ' ' + element.xpath('fb:middle-name/text()', | ||||
|                             namespaces=ns)[0] + ' ' + element.xpath('fb:last-name/text()', namespaces=ns)[0] | ||||
|     author = ", ".join(map(get_author, authors)) | ||||
|         last_name=element.xpath('fb:last-name/text()', namespaces=ns) | ||||
|         if len(last_name): | ||||
|             last_name=last_name[0] | ||||
|         else: | ||||
|             last_name=u'' | ||||
|         middle_name=element.xpath('fb:middle-name/text()', namespaces=ns) | ||||
|         if len(middle_name): | ||||
|             middle_name=middle_name[0] | ||||
|         else: | ||||
|             middle_name=u'' | ||||
|         first_name=element.xpath('fb:first-name/text()', namespaces=ns) | ||||
|         if len(first_name): | ||||
|             first_name=first_name[0] | ||||
|         else: | ||||
|             first_name=u'' | ||||
|         return  first_name + ' ' + middle_name + ' ' + last_name | ||||
|  | ||||
|     author = unicode(", ".join(map(get_author, authors))) | ||||
|  | ||||
|     title = tree.xpath('/fb:FictionBook/fb:description/fb:title-info/fb:book-title/text()', namespaces=ns) | ||||
|     if len(title): | ||||
|         title=unicode(title[0]) | ||||
|     else: | ||||
|         title=u'' | ||||
|     description = tree.xpath('/fb:FictionBook/fb:description/fb:publish-info/fb:book-name/text()', namespaces=ns) | ||||
|     if len(description): | ||||
|         description=unicode(description[0]) | ||||
|     else: | ||||
|         description=u'' | ||||
|  | ||||
|  | ||||
|     title = unicode(tree.xpath('/fb:FictionBook/fb:description/fb:title-info/fb:book-title/text()', namespaces=ns)[0]) | ||||
|     description = unicode(tree.xpath('/fb:FictionBook/fb:description/fb:publish-info/fb:book-name/text()', | ||||
|                                      namespaces=ns)[0]) | ||||
|  | ||||
|     return uploader.BookMeta( | ||||
|         file_path=tmp_file_path, | ||||
|         extension=original_file_extension, | ||||
|         title=title, | ||||
|         author=author, | ||||
|         title=title.encode('utf-8').decode('utf-8'), | ||||
|         author=author.encode('utf-8').decode('utf-8'), | ||||
|         cover=None, | ||||
|         description=description, | ||||
|         tags="", | ||||
|   | ||||
| @@ -16,6 +16,13 @@ | ||||
|     <link type="application/atom+xml;profile=opds-catalog;type=feed;kind=acquisition" href="{{url_for('feed_hot')}}" /> | ||||
|     <link type="application/atom+xml" href="{{url_for('feed_hot')}}" rel="http://opds-spec.org/sort/popular"/> | ||||
|     <id>{{url_for('feed_hot')}}</id> | ||||
|     <content type="text">{{_('Popular publications from this catalog based on Downloads.')}}</content> | ||||
|   </entry> | ||||
|   <entry> | ||||
|     <title>{{_('Best rated Books')}}</title> | ||||
|     <link type="application/atom+xml;profile=opds-catalog;type=feed;kind=acquisition" href="{{url_for('feed_best_rated')}}" /> | ||||
|     <link type="application/atom+xml" href="{{url_for('feed_best_rated')}}" rel="http://opds-spec.org/recommended"/> | ||||
|     <id>{{url_for('feed_best_rated')}}</id> | ||||
|     <content type="text">{{_('Popular publications from this catalog based on Rating.')}}</content> | ||||
|   </entry> | ||||
|   <entry> | ||||
|   | ||||
| @@ -123,6 +123,9 @@ | ||||
|               {% if g.user.show_hot_books() %} | ||||
|               <li><a href="{{url_for('hot_books')}}"><span class="glyphicon glyphicon-fire"></span> {{_('Hot Books')}}</a></li> | ||||
|               {%endif%} | ||||
|               {% if g.user.show_best_rated_books() %} | ||||
|               <li><a href="{{url_for('best_rated_books')}}"><span class="glyphicon glyphicon-star"></span> {{_('Best rated Books')}}</a></li> | ||||
|               {%endif%} | ||||
|               {% if g.user.show_random_books() %} | ||||
|               <li><a href="{{url_for('discover')}}"><span class="glyphicon glyphicon-random"></span> {{_('Discover')}}</a></li> | ||||
|               {%endif%} | ||||
|   | ||||
| @@ -21,7 +21,7 @@ | ||||
|       </div> | ||||
|       <div class="meta"> | ||||
|         <p class="title">{{entry.title|shortentitle}}</p> | ||||
|         <p class="author"><a href="{{url_for('author', name=entry.authors[0].name | urlencode) }}">{{entry.authors[0].name}}</a></p> | ||||
|         <p class="author"><a href="{{url_for('author', id=entry.authors[0].id) }}">{{entry.authors[0].name}}</a></p> | ||||
|         {% if entry.ratings.__len__() > 0 %} | ||||
|         <div class="rating"> | ||||
|           {% for number in range((entry.ratings[0].rating/2)|int(2)) %} | ||||
|   | ||||
| @@ -48,6 +48,10 @@ | ||||
|         <input type="checkbox" name="show_hot" id="show_hot" {% if content.show_hot_books() %}checked{% endif %}> | ||||
|         <label for="show_hot">{{_('Show hot books')}}</label> | ||||
|     </div> | ||||
|     <div class="form-group"> | ||||
|         <input type="checkbox" name="show_best_rated" id="show_best_rated" {% if content.show_best_rated_books() %}checked{% endif %}> | ||||
|         <label for="show_best_rated">{{_('Show best rated books')}}</label> | ||||
|     </div> | ||||
|     <div class="form-group"> | ||||
|         <input type="checkbox" name="show_language" id="show_language" {% if content.show_language() %}checked{% endif %}> | ||||
|         <label for="show_language">{{_('Show language selection')}}</label> | ||||
|   | ||||
| @@ -31,6 +31,7 @@ SIDEBAR_CATEGORY = 8 | ||||
| SIDEBAR_HOT = 16 | ||||
| SIDEBAR_RANDOM = 32 | ||||
| SIDEBAR_AUTHOR = 64 | ||||
| SIDEBAR_BEST_RATED = 128 | ||||
|  | ||||
| DEFAULT_PASS = "admin123" | ||||
|  | ||||
| @@ -130,6 +131,12 @@ class UserBase: | ||||
|         else: | ||||
|             return False | ||||
|  | ||||
|     def show_best_rated_books(self): | ||||
|         if self.sidebar_view is not None: | ||||
|             return True if self.sidebar_view & SIDEBAR_BEST_RATED == SIDEBAR_BEST_RATED else False | ||||
|         else: | ||||
|             return False | ||||
|  | ||||
|     def show_detail_random(self): | ||||
|         if self.sidebar_view is not None: | ||||
|             return True if self.sidebar_view & DETAIL_RANDOM == DETAIL_RANDOM else False | ||||
| @@ -412,7 +419,7 @@ def create_admin_user(): | ||||
|     user.nickname = "admin" | ||||
|     user.role = ROLE_USER + ROLE_ADMIN + ROLE_DOWNLOAD + ROLE_UPLOAD + ROLE_EDIT + ROLE_PASSWD | ||||
|     user.sidebar_view = DETAIL_RANDOM + SIDEBAR_LANGUAGE + SIDEBAR_SERIES + SIDEBAR_CATEGORY + SIDEBAR_HOT + \ | ||||
|         SIDEBAR_RANDOM + SIDEBAR_AUTHOR | ||||
|         SIDEBAR_RANDOM + SIDEBAR_AUTHOR + SIEDBAR_BEST_RATED | ||||
|  | ||||
|     user.password = generate_password_hash(DEFAULT_PASS) | ||||
|  | ||||
|   | ||||
							
								
								
									
										59
									
								
								cps/web.py
									
									
									
									
									
								
							
							
						
						
									
										59
									
								
								cps/web.py
									
									
									
									
									
								
							| @@ -509,14 +509,37 @@ def feed_discover(): | ||||
|     return response | ||||
|  | ||||
|  | ||||
| @app.route("/opds/rated") | ||||
| @requires_basic_auth_if_no_ano | ||||
| def feed_best_rated(): | ||||
|     off = request.args.get("offset") | ||||
|     if not off: | ||||
|         off = 0 | ||||
|     entries, random, pagination = fill_indexpage((int(off) / (int(config.config_books_per_page)) + 1), | ||||
|                     db.Books, db.Books.ratings.any(db.Ratings.rating > 9), db.Books.timestamp.desc()) | ||||
|     xml = render_title_template('feed.xml', entries=entries, pagination=pagination) | ||||
|     response = make_response(xml) | ||||
|     response.headers["Content-Type"] = "application/xml" | ||||
|     return response | ||||
|  | ||||
| @app.route("/opds/hot") | ||||
| @requires_basic_auth_if_no_ano | ||||
| def feed_hot(): | ||||
|     off = request.args.get("offset") | ||||
|     if not off: | ||||
|         off = 0 | ||||
|     entries, random, pagination = fill_indexpage((int(off) / (int(config.config_books_per_page)) + 1), | ||||
|                     db.Books, db.Books.ratings.any(db.Ratings.rating > 9), db.Books.timestamp.desc()) | ||||
|     if current_user.filter_language() != "all": | ||||
|         filter = db.Books.languages.any(db.Languages.lang_code == current_user.filter_language()) | ||||
|     else: | ||||
|         filter = True | ||||
|     all_books = ub.session.query(ub.Downloads, ub.func.count(ub.Downloads.book_id)).order_by( | ||||
|         ub.func.count(ub.Downloads.book_id).desc()).group_by(ub.Downloads.book_id) | ||||
|     hot_books = all_books.offset(off).limit(config.config_books_per_page) | ||||
|     entries = list() | ||||
|     for book in hot_books: | ||||
|         entries.append(db.session.query(db.Books).filter(filter).filter(db.Books.id == book.Downloads.book_id).first()) | ||||
|     numBooks = entries.__len__() | ||||
|     pagination = Pagination((int(off) / (int(config.config_books_per_page)) + 1), config.config_books_per_page, numBooks) | ||||
|     xml = render_title_template('feed.xml', entries=entries, pagination=pagination) | ||||
|     response = make_response(xml) | ||||
|     response.headers["Content-Type"] = "application/xml" | ||||
| @@ -779,6 +802,16 @@ def hot_books(page): | ||||
|                                  title=_(u"Hot Books (most downloaded)")) | ||||
|  | ||||
|  | ||||
| @app.route("/rated", defaults={'page': 1}) | ||||
| @app.route('/rated/page/<int:page>') | ||||
| @login_required_if_no_ano | ||||
| def best_rated_books(page): | ||||
|     entries, random, pagination = fill_indexpage(page, db.Books, db.Books.ratings.any(db.Ratings.rating > 9), | ||||
|                                                  db.Books.timestamp.desc()) | ||||
|     return render_title_template('index.html', random=random, entries=entries, pagination=pagination, | ||||
|                                  title=_(u"Best rated books")) | ||||
|  | ||||
|  | ||||
| @app.route("/discover", defaults={'page': 1}) | ||||
| @app.route('/discover/page/<int:page>') | ||||
| @login_required_if_no_ano | ||||
| @@ -1519,6 +1552,8 @@ def profile(): | ||||
|             content.sidebar_view += ub.SIDEBAR_CATEGORY | ||||
|         if "show_hot" in to_save: | ||||
|             content.sidebar_view += ub.SIDEBAR_HOT | ||||
|         if "show_best_rated" in to_save: | ||||
|             content.sidebar_view += ub.SIDEBAR_BEST_RATED | ||||
|         if "show_author" in to_save: | ||||
|             content.sidebar_view += ub.SIDEBAR_AUTHOR | ||||
|         if "show_detail_random" in to_save: | ||||
| @@ -1670,6 +1705,8 @@ def new_user(): | ||||
|             content.sidebar_view += ub.SIDEBAR_CATEGORY | ||||
|         if "show_hot" in to_save: | ||||
|             content.sidebar_view += ub.SIDEBAR_HOT | ||||
|         if "show_best_rated" in to_save: | ||||
|             content.sidebar_view += ub.SIDEBAR_BEST_RATED | ||||
|         if "show_author" in to_save: | ||||
|             content.sidebar_view += ub.SIDEBAR_AUTHOR | ||||
|         if "show_detail_random" in to_save: | ||||
| @@ -1806,6 +1843,11 @@ def edit_user(user_id): | ||||
|             elif "show_hot" not in to_save and content.show_hot_books(): | ||||
|                 content.sidebar_view -= ub.SIDEBAR_HOT | ||||
|  | ||||
|             if "show_best_rated" in to_save and not content.show_best_rated_books(): | ||||
|                 content.sidebar_view += ub.SIDEBAR_BEST_RATED | ||||
|             elif "show_best_rated" not in to_save and content.show_best_rated_books(): | ||||
|                 content.sidebar_view -= ub.SIDEBAR_BEST_RATED | ||||
|  | ||||
|             if "show_author" in to_save and not content.show_author(): | ||||
|                 content.sidebar_view += ub.SIDEBAR_AUTHOR | ||||
|             elif "show_author" not in to_save and content.show_author(): | ||||
| @@ -1870,6 +1912,7 @@ def edit_book(book_id): | ||||
|             modify_database_object(input_authors, book.authors, db.Authors, db.session, 'author') | ||||
|             if author0_before_edit != book.authors[0].name: | ||||
|                 edited_books_id.add(book.id) | ||||
|                 book.author_sort=helper.get_normalized_author(input_authors[0]) # ToDo: wrong sorting | ||||
|  | ||||
|             if to_save["cover_url"] and os.path.splitext(to_save["cover_url"])[1].lower() == ".jpg": | ||||
|                 img = requests.get(to_save["cover_url"]) | ||||
| @@ -2059,11 +2102,11 @@ def upload(): | ||||
|         file = request.files['btn-upload'] | ||||
|         meta = uploader.upload(file) | ||||
|  | ||||
|         title = meta.title.encode('utf-8') | ||||
|         author = meta.author.encode('utf-8') | ||||
|         title = meta.title | ||||
|         author = meta.author | ||||
|  | ||||
|         title_dir = helper.get_valid_filename(title.decode('utf-8'), False) | ||||
|         author_dir = helper.get_valid_filename(author.decode('utf-8'), False) | ||||
|         title_dir = helper.get_valid_filename(title, False) | ||||
|         author_dir = helper.get_valid_filename(author, False) | ||||
|         data_name = title_dir | ||||
|         filepath = config.config_calibre_dir + os.sep + author_dir + os.sep + title_dir | ||||
|         saved_filename = filepath + os.sep + data_name + meta.extension | ||||
| @@ -2097,10 +2140,10 @@ def upload(): | ||||
|         if is_author: | ||||
|             db_author = is_author | ||||
|         else: | ||||
|             db_author = db.Authors(author, "", "") | ||||
|             db_author = db.Authors(author, helper.get_normalized_author(author), "") # TODO: WRONG Sorting Author function | ||||
|             db.session.add(db_author) | ||||
|         path = os.path.join(author_dir, title_dir) | ||||
|         db_book = db.Books(title, "", "", datetime.datetime.now(), datetime.datetime(101, 01, 01), 1, | ||||
|         db_book = db.Books(title, "", db_author.sort, datetime.datetime.now(), datetime.datetime(101, 01, 01), 1, | ||||
|                            datetime.datetime.now(), path, has_cover, db_author, []) | ||||
|         db_book.authors.append(db_author) | ||||
|         db_data = db.Data(db_book, meta.extension.upper()[1:], file_size, data_name) | ||||
|   | ||||
							
								
								
									
										2483
									
								
								vendor/configobj.py
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2483
									
								
								vendor/configobj.py
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
		Reference in New Issue
	
	Block a user
	 Ethan Lin
					Ethan Lin