bugfix on create shelv via kobo sync protocol
bugfix for totally wrong json requests prevent empty shelf names on kobo create shelf Removed errorhandler 404
This commit is contained in:
		
							parent
							
								
									e29f17ac46
								
							
						
					
					
						commit
						8b8fe7a0ae
					
				
							
								
								
									
										157
									
								
								cps/kobo.py
									
									
									
									
									
								
							
							
						
						
									
										157
									
								
								cps/kobo.py
									
									
									
									
									
								
							|  | @ -45,6 +45,7 @@ from flask_login import current_user, login_required | |||
| from werkzeug.datastructures import Headers | ||||
| from sqlalchemy import func | ||||
| from sqlalchemy.sql.expression import and_, or_ | ||||
| from sqlalchemy.exc import StatementError | ||||
| import requests | ||||
| 
 | ||||
| from . import config, logger, kobo_auth, db, helper, shelf as shelf_lib, ub | ||||
|  | @ -222,10 +223,10 @@ def HandleSyncRequest(): | |||
|     sync_token.archive_last_modified = new_archived_last_modified | ||||
|     sync_token.reading_state_last_modified = new_reading_state_last_modified | ||||
| 
 | ||||
|     return generate_sync_response(request, sync_token, sync_results) | ||||
|     return generate_sync_response(sync_token, sync_results) | ||||
| 
 | ||||
| 
 | ||||
| def generate_sync_response(request, sync_token, sync_results): | ||||
| def generate_sync_response(sync_token, sync_results): | ||||
|     extra_headers = {} | ||||
|     if config.config_kobo_proxy: | ||||
|         # Merge in sync results from the official Kobo store. | ||||
|  | @ -394,26 +395,31 @@ def get_metadata(book): | |||
|     return metadata | ||||
| 
 | ||||
| 
 | ||||
| @kobo.route("/v1/library/tags", methods=["POST"]) | ||||
| @kobo.route("/v1/library/tags", methods=["POST", "DELETE"]) | ||||
| @login_required | ||||
| # Creates a Shelf with the given items, and returns the shelf's uuid. | ||||
| def HandleTagCreate(): | ||||
|     shelf_request = request.json | ||||
|     # catch delete requests, otherwise the are handeld in the book delete handler | ||||
|     if request.method == "DELETE": | ||||
|         abort(405) | ||||
|     name, items = None, None | ||||
|     try: | ||||
|         shelf_request = request.json | ||||
|         name = shelf_request["Name"] | ||||
|         items = shelf_request["Items"] | ||||
|     except KeyError: | ||||
|         if not name: | ||||
|             raise TypeError | ||||
|     except (KeyError, TypeError): | ||||
|         log.debug("Received malformed v1/library/tags request.") | ||||
|         abort(400, description="Malformed tags POST request. Data is missing 'Name' or 'Items' field") | ||||
|         abort(400, description="Malformed tags POST request. Data has empty 'Name', missing 'Name' or 'Items' field") | ||||
| 
 | ||||
|     shelf = ub.session.query(ub.Shelf).filter(ub.Shelf.name == name, ub.Shelf.user_id == | ||||
|                                               current_user.id).one_or_none() | ||||
|     if shelf and not shelf_lib.check_shelf_edit_permissions(shelf): | ||||
|         abort(401, description="User is unauthaurized to edit shelf.") | ||||
|         abort(401, description="User is unauthaurized to create shelf.") | ||||
| 
 | ||||
|     if not shelf: | ||||
|         shelf = ub.Shelf(user_id=current_user.id, name=name, uuid=uuid.uuid4()) | ||||
|         shelf = ub.Shelf(user_id=current_user.id, name=name, uuid=str(uuid.uuid4())) | ||||
|         ub.session.add(shelf) | ||||
| 
 | ||||
|     items_unknown_to_calibre = add_items_to_shelf(items, shelf) | ||||
|  | @ -441,18 +447,17 @@ def HandleTagUpdate(tag_id): | |||
|     if request.method == "DELETE": | ||||
|         shelf_lib.delete_shelf_helper(shelf) | ||||
|     else: | ||||
|         shelf_request = request.json | ||||
|         name = None | ||||
|         try: | ||||
|             shelf_request = request.json | ||||
|             name = shelf_request["Name"] | ||||
|         except KeyError: | ||||
|         except (KeyError, TypeError): | ||||
|             log.debug("Received malformed v1/library/tags rename request.") | ||||
|             abort(400, description="Malformed tags POST request. Data is missing 'Name' field") | ||||
| 
 | ||||
|         shelf.name = name | ||||
|         ub.session.merge(shelf) | ||||
|         ub.session.commit() | ||||
| 
 | ||||
|     return make_response(' ', 200) | ||||
| 
 | ||||
| 
 | ||||
|  | @ -461,29 +466,32 @@ def add_items_to_shelf(items, shelf): | |||
|     book_ids_already_in_shelf = set([book_shelf.book_id for book_shelf in shelf.books]) | ||||
|     items_unknown_to_calibre = [] | ||||
|     for item in items: | ||||
|         if item["Type"] != "ProductRevisionTagItem": | ||||
|             items_unknown_to_calibre.append(item) | ||||
|             continue | ||||
|         try: | ||||
|             if item["Type"] != "ProductRevisionTagItem": | ||||
|                 items_unknown_to_calibre.append(item) | ||||
|                 continue | ||||
| 
 | ||||
|         book = db.session.query(db.Books).filter(db.Books.uuid == item["RevisionId"]).one_or_none() | ||||
|         if not book: | ||||
|             items_unknown_to_calibre.append(item) | ||||
|             continue | ||||
|             book = db.session.query(db.Books).filter(db.Books.uuid == item["RevisionId"]).one_or_none() | ||||
|             if not book: | ||||
|                 items_unknown_to_calibre.append(item) | ||||
|                 continue | ||||
| 
 | ||||
|         book_id = book.id | ||||
|         if book_id not in book_ids_already_in_shelf: | ||||
|             shelf.books.append(ub.BookShelf(book_id=book_id)) | ||||
|             book_id = book.id | ||||
|             if book_id not in book_ids_already_in_shelf: | ||||
|                 shelf.books.append(ub.BookShelf(book_id=book_id)) | ||||
|         except KeyError: | ||||
|             items_unknown_to_calibre.append(item) | ||||
|     return items_unknown_to_calibre | ||||
| 
 | ||||
| 
 | ||||
| @kobo.route("/v1/library/tags/<tag_id>/items", methods=["POST"]) | ||||
| @login_required | ||||
| def HandleTagAddItem(tag_id): | ||||
|     tag_request = request.json | ||||
|     items = None | ||||
|     try: | ||||
|         tag_request = request.json | ||||
|         items = tag_request["Items"] | ||||
|     except KeyError: | ||||
|     except (KeyError, TypeError): | ||||
|         log.debug("Received malformed v1/library/tags/<tag_id>/items/delete request.") | ||||
|         abort(400, description="Malformed tags POST request. Data is missing 'Items' field") | ||||
| 
 | ||||
|  | @ -509,15 +517,14 @@ def HandleTagAddItem(tag_id): | |||
| @kobo.route("/v1/library/tags/<tag_id>/items/delete", methods=["POST"]) | ||||
| @login_required | ||||
| def HandleTagRemoveItem(tag_id): | ||||
|     tag_request = request.json | ||||
|     items = None | ||||
|     try: | ||||
|         tag_request = request.json | ||||
|         items = tag_request["Items"] | ||||
|     except KeyError: | ||||
|     except (KeyError, TypeError): | ||||
|         log.debug("Received malformed v1/library/tags/<tag_id>/items/delete request.") | ||||
|         abort(400, description="Malformed tags POST request. Data is missing 'Items' field") | ||||
| 
 | ||||
|     # insconsitent to above requests | ||||
|     shelf = ub.session.query(ub.Shelf).filter(ub.Shelf.uuid == tag_id, | ||||
|                                               ub.Shelf.user_id == current_user.id).one_or_none() | ||||
|     if not shelf: | ||||
|  | @ -530,16 +537,19 @@ def HandleTagRemoveItem(tag_id): | |||
| 
 | ||||
|     items_unknown_to_calibre = [] | ||||
|     for item in items: | ||||
|         if item["Type"] != "ProductRevisionTagItem": | ||||
|             items_unknown_to_calibre.append(item) | ||||
|             continue | ||||
|         try: | ||||
|             if item["Type"] != "ProductRevisionTagItem": | ||||
|                 items_unknown_to_calibre.append(item) | ||||
|                 continue | ||||
| 
 | ||||
|         book = db.session.query(db.Books).filter(db.Books.uuid == item["RevisionId"]).one_or_none() | ||||
|         if not book: | ||||
|             items_unknown_to_calibre.append(item) | ||||
|             continue | ||||
|             book = db.session.query(db.Books).filter(db.Books.uuid == item["RevisionId"]).one_or_none() | ||||
|             if not book: | ||||
|                 items_unknown_to_calibre.append(item) | ||||
|                 continue | ||||
| 
 | ||||
|         shelf.books.filter(ub.BookShelf.book_id == book.id).delete() | ||||
|             shelf.books.filter(ub.BookShelf.book_id == book.id).delete() | ||||
|         except KeyError: | ||||
|             items_unknown_to_calibre.append(item) | ||||
|     ub.session.commit() | ||||
| 
 | ||||
|     if items_unknown_to_calibre: | ||||
|  | @ -628,39 +638,43 @@ def HandleStateRequest(book_uuid): | |||
|     else: | ||||
|         update_results_response = {"EntitlementId": book_uuid} | ||||
| 
 | ||||
|         request_data = request.json | ||||
|         if "ReadingStates" not in request_data: | ||||
|         try: | ||||
|             request_data = request.json | ||||
|             request_reading_state = request_data["ReadingStates"][0] | ||||
| 
 | ||||
|             request_bookmark = request_reading_state["CurrentBookmark"] | ||||
|             if request_bookmark: | ||||
|                 current_bookmark = kobo_reading_state.current_bookmark | ||||
|                 current_bookmark.progress_percent = request_bookmark["ProgressPercent"] | ||||
|                 current_bookmark.content_source_progress_percent = request_bookmark["ContentSourceProgressPercent"] | ||||
|                 location = request_bookmark["Location"] | ||||
|                 if location: | ||||
|                     current_bookmark.location_value = location["Value"] | ||||
|                     current_bookmark.location_type = location["Type"] | ||||
|                     current_bookmark.location_source = location["Source"] | ||||
|                 update_results_response["CurrentBookmarkResult"] = {"Result": "Success"} | ||||
| 
 | ||||
|             request_statistics = request_reading_state["Statistics"] | ||||
|             if request_statistics: | ||||
|                 statistics = kobo_reading_state.statistics | ||||
|                 statistics.spent_reading_minutes = int(request_statistics["SpentReadingMinutes"]) | ||||
|                 statistics.remaining_time_minutes = int(request_statistics["RemainingTimeMinutes"]) | ||||
|                 update_results_response["StatisticsResult"] = {"Result": "Success"} | ||||
| 
 | ||||
|             request_status_info = request_reading_state["StatusInfo"] | ||||
|             if request_status_info: | ||||
|                 book_read = kobo_reading_state.book_read_link | ||||
|                 new_book_read_status = get_ub_read_status(request_status_info["Status"]) | ||||
|                 if new_book_read_status == ub.ReadBook.STATUS_IN_PROGRESS \ | ||||
|                     and new_book_read_status != book_read.read_status: | ||||
|                     book_read.times_started_reading += 1 | ||||
|                     book_read.last_time_started_reading = datetime.datetime.utcnow() | ||||
|                 book_read.read_status = new_book_read_status | ||||
|                 update_results_response["StatusInfoResult"] = {"Result": "Success"} | ||||
|         except (KeyError, TypeError, ValueError, StatementError): | ||||
|             log.debug("Received malformed v1/library/<book_uuid>/state request.") | ||||
|             ub.session.rollback() | ||||
|             abort(400, description="Malformed request data is missing 'ReadingStates' key") | ||||
|         request_reading_state = request_data["ReadingStates"][0] | ||||
| 
 | ||||
|         request_bookmark = request_reading_state.get("CurrentBookmark") | ||||
|         if request_bookmark: | ||||
|             current_bookmark = kobo_reading_state.current_bookmark | ||||
|             current_bookmark.progress_percent = request_bookmark.get("ProgressPercent") | ||||
|             current_bookmark.content_source_progress_percent = request_bookmark.get("ContentSourceProgressPercent") | ||||
|             location = request_bookmark.get("Location") | ||||
|             if location: | ||||
|                 current_bookmark.location_value = location.get("Value") | ||||
|                 current_bookmark.location_type = location.get("Type") | ||||
|                 current_bookmark.location_source = location.get("Source") | ||||
|             update_results_response["CurrentBookmarkResult"] = {"Result": "Success"} | ||||
| 
 | ||||
|         request_statistics = request_reading_state.get("Statistics") | ||||
|         if request_statistics: | ||||
|             statistics = kobo_reading_state.statistics | ||||
|             statistics.spent_reading_minutes = request_statistics.get("SpentReadingMinutes") | ||||
|             statistics.remaining_time_minutes = request_statistics.get("RemainingTimeMinutes") | ||||
|             update_results_response["StatisticsResult"] = {"Result": "Success"} | ||||
| 
 | ||||
|         request_status_info = request_reading_state.get("StatusInfo") | ||||
|         if request_status_info: | ||||
|             book_read = kobo_reading_state.book_read_link | ||||
|             new_book_read_status = get_ub_read_status(request_status_info.get("Status")) | ||||
|             if new_book_read_status == ub.ReadBook.STATUS_IN_PROGRESS and new_book_read_status != book_read.read_status: | ||||
|                 book_read.times_started_reading += 1 | ||||
|                 book_read.last_time_started_reading = datetime.datetime.utcnow() | ||||
|             book_read.read_status = new_book_read_status | ||||
|             update_results_response["StatusInfoResult"] = {"Result": "Success"} | ||||
| 
 | ||||
|         ub.session.merge(kobo_reading_state) | ||||
|         ub.session.commit() | ||||
|  | @ -691,8 +705,8 @@ def get_ub_read_status(kobo_read_status): | |||
| 
 | ||||
| 
 | ||||
| def get_or_create_reading_state(book_id): | ||||
|     book_read = ub.session.query(ub.ReadBook).filter(and_(ub.ReadBook.book_id == book_id, | ||||
|                                                           ub.ReadBook.user_id == current_user.id)).one_or_none() | ||||
|     book_read = ub.session.query(ub.ReadBook).filter(ub.ReadBook.book_id == book_id, | ||||
|                                                           ub.ReadBook.user_id == current_user.id).one_or_none() | ||||
|     if not book_read: | ||||
|         book_read = ub.ReadBook(user_id=current_user.id, book_id=book_id) | ||||
|     if not book_read.kobo_reading_state: | ||||
|  | @ -840,12 +854,15 @@ def HandleProductsRequest(dummy=None): | |||
|     return redirect_or_proxy_request() | ||||
| 
 | ||||
| 
 | ||||
| @kobo.app_errorhandler(404) | ||||
| '''@kobo.errorhandler(404) | ||||
| def handle_404(err): | ||||
|     # This handler acts as a catch-all for endpoints that we don't have an interest in | ||||
|     # implementing (e.g: v1/analytics/gettests, v1/user/recommendations, etc) | ||||
|     if err: | ||||
|         print('404') | ||||
|         return jsonify(error=str(err)), 404 | ||||
|     log.debug("Unknown Request received: %s, method: %s, data: %s", request.base_url, request.method, request.data) | ||||
|     return redirect_or_proxy_request() | ||||
|     return redirect_or_proxy_request()''' | ||||
| 
 | ||||
| 
 | ||||
| def make_calibre_web_auth_response(): | ||||
|  |  | |||
							
								
								
									
										2
									
								
								cps/server.py
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
						
						
									
										2
									
								
								cps/server.py
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							|  | @ -24,7 +24,7 @@ import signal | |||
| import socket | ||||
| 
 | ||||
| try: | ||||
|     from gevent.pywtsgi import WSGIServer | ||||
|     from gevent.pywsgi import WSGIServer | ||||
|     from gevent.pool import Pool | ||||
|     from gevent import __version__ as _version | ||||
|     VERSION = 'Gevent ' + _version | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	Block a user