Save ePub bookmarks to database
Save ePub bookmark to database. Also use library's built-in restore feature to restore all information from localStorage.
This commit is contained in:
		
							parent
							
								
									193605df4a
								
							
						
					
					
						commit
						374b5f4c6e
					
				
							
								
								
									
										38
									
								
								cps/static/js/reading/epub.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								cps/static/js/reading/epub.js
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,38 @@ | ||||||
|  | /* global $, calibre, EPUBJS, ePubReader */ | ||||||
|  | 
 | ||||||
|  | (function() { | ||||||
|  |     "use strict"; | ||||||
|  | 
 | ||||||
|  |     EPUBJS.filePath = calibre.filePath; | ||||||
|  |     EPUBJS.cssPath = calibre.cssPath; | ||||||
|  | 
 | ||||||
|  |     var reader = ePubReader(calibre.bookUrl, { | ||||||
|  |         restore: true, | ||||||
|  |         bookmarks: [calibre.bookmark] | ||||||
|  |     }); | ||||||
|  |     reader.on("reader:bookmarked", updateBookmark.bind(reader, "add")); | ||||||
|  |     reader.on("reader:unbookmarked", updateBookmark.bind(reader, "remove")); | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * @param {string} action - Add or remove bookmark | ||||||
|  |      * @param {string|int} location - Location or zero | ||||||
|  |      */ | ||||||
|  |     function updateBookmark(action, location) { | ||||||
|  |         // Remove other bookmarks (there can only be one)
 | ||||||
|  |         if (action === "add") { | ||||||
|  |             this.settings.bookmarks.filter(function (bookmark) { | ||||||
|  |                 return bookmark !== location; | ||||||
|  |             }).map(function (bookmark) { | ||||||
|  |                 this.removeBookmark(bookmark); | ||||||
|  |             }.bind(this)); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         // Save to database
 | ||||||
|  |         $.ajax(calibre.bookmarkUrl, { | ||||||
|  |             method: "post", | ||||||
|  |             data: { bookmark: location || "" } | ||||||
|  |         }).fail(function (xhr, status, error) { | ||||||
|  |             alert(error); | ||||||
|  |         }); | ||||||
|  |     } | ||||||
|  | })(); | ||||||
|  | @ -11,59 +11,6 @@ | ||||||
|         <link rel="stylesheet" href="{{ url_for('static', filename='css/libs/normalize.css') }}"> |         <link rel="stylesheet" href="{{ url_for('static', filename='css/libs/normalize.css') }}"> | ||||||
|         <link rel="stylesheet" href="{{ url_for('static', filename='css/main.css') }}"> |         <link rel="stylesheet" href="{{ url_for('static', filename='css/main.css') }}"> | ||||||
|         <link rel="stylesheet" href="{{ url_for('static', filename='css/popup.css') }}"> |         <link rel="stylesheet" href="{{ url_for('static', filename='css/popup.css') }}"> | ||||||
|         <script src="{{ url_for('static', filename='js/libs/jquery.min.js') }}"></script> |  | ||||||
|         <script src="{{ url_for('static', filename='js/libs/zip.min.js') }}"></script> |  | ||||||
| 
 |  | ||||||
|         <!-- Full Screen --> |  | ||||||
|         <script src="{{ url_for('static', filename='js/libs/screenfull.min.js') }}"></script> |  | ||||||
| 
 |  | ||||||
|         <!-- Render --> |  | ||||||
|         <script src="{{ url_for('static', filename='js/libs/epub.min.js') }}"></script> |  | ||||||
| 
 |  | ||||||
|         <!-- Hooks --> |  | ||||||
|         <script src="{{ url_for('static', filename='js/libs/hooks.min.js') }}"></script> |  | ||||||
| 
 |  | ||||||
|         <!-- Reader --> |  | ||||||
|         <script src="{{ url_for('static', filename='js/libs/reader.min.js') }}"></script> |  | ||||||
| 
 |  | ||||||
|         <script> |  | ||||||
|             "use strict"; |  | ||||||
|             document.onreadystatechange = function () { |  | ||||||
|               if (document.readyState == "complete") { |  | ||||||
|                 EPUBJS.filePath = "{{ url_for('static', filename='js/libs/') }}"; |  | ||||||
|                 EPUBJS.cssPath = "{{ url_for('static', filename='css/') }}"; |  | ||||||
| 
 |  | ||||||
|                 window.reader = ePubReader("{{ url_for('static', filename=bookid) }}/"); |  | ||||||
|                 //keybind |  | ||||||
|                 /*$(document).keydown(function(event){ |  | ||||||
|                   if(event.keyCode == 37){ |  | ||||||
|                     //window.reader.book.prevPage(); |  | ||||||
|                     event.preventDefault(); |  | ||||||
|                   } |  | ||||||
|                   if(event.keyCode == 39){ |  | ||||||
|                     //swindow.reader.book.nextPage(); |  | ||||||
|                     event.preventDefault(); |  | ||||||
|                   } |  | ||||||
|                 }); |  | ||||||
|                 //bind mouse |  | ||||||
|                 $(window).bind('DOMMouseScroll mousewheel', function(event) { |  | ||||||
|                   var delta = 0; |  | ||||||
|                   if (event.originalEvent.wheelDelta) { |  | ||||||
|                     delta = event.originalEvent.wheelDelta; |  | ||||||
|                   }else if (event.originalEvent.detail) { |  | ||||||
|                     delta = event.originalEvent.detail*-1; |  | ||||||
|                   } |  | ||||||
|                   if (delta >= 0) { |  | ||||||
|                     window.reader.book.prevPage(); |  | ||||||
|                   } |  | ||||||
|                   else { |  | ||||||
|                     window.reader.book.nextPage(); |  | ||||||
|                   } |  | ||||||
|                 });*/ |  | ||||||
|               } |  | ||||||
|             }; |  | ||||||
|         </script> |  | ||||||
| 
 |  | ||||||
|     </head> |     </head> | ||||||
|     <body> |     <body> | ||||||
|       <div id="sidebar"> |       <div id="sidebar"> | ||||||
|  | @ -129,5 +76,22 @@ | ||||||
|           </div> |           </div> | ||||||
|       </div> |       </div> | ||||||
|       <div class="overlay"></div> |       <div class="overlay"></div> | ||||||
|  | 
 | ||||||
|  |       <script type="text/javascript"> | ||||||
|  |           window.calibre = { | ||||||
|  |               filePath: "{{ url_for('static', filename='js/libs/') }}", | ||||||
|  |               cssPath: "{{ url_for('static', filename='css/') }}", | ||||||
|  |               bookUrl: "{{ url_for('static', filename=bookid) }}/", | ||||||
|  |               bookmarkUrl: "{{ url_for('bookmark', book_id=bookid, book_format='EPUB') }}", | ||||||
|  |               bookmark: "{{ bookmark.bookmark_key if bookmark != None }}" | ||||||
|  |           }; | ||||||
|  |       </script> | ||||||
|  |       <script src="{{ url_for('static', filename='js/libs/jquery.min.js') }}"></script> | ||||||
|  |       <script src="{{ url_for('static', filename='js/libs/zip.min.js') }}"></script> | ||||||
|  |       <script src="{{ url_for('static', filename='js/libs/screenfull.min.js') }}"></script> | ||||||
|  |       <script src="{{ url_for('static', filename='js/libs/epub.min.js') }}"></script> | ||||||
|  |       <script src="{{ url_for('static', filename='js/libs/hooks.min.js') }}"></script> | ||||||
|  |       <script src="{{ url_for('static', filename='js/libs/reader.min.js') }}"></script> | ||||||
|  |       <script src="{{ url_for('static', filename='js/reading/epub.js') }}"></script> | ||||||
|     </body> |     </body> | ||||||
| </html> | </html> | ||||||
|  |  | ||||||
							
								
								
									
										19
									
								
								cps/ub.py
									
									
									
									
									
								
							
							
						
						
									
										19
									
								
								cps/ub.py
									
									
									
									
									
								
							|  | @ -212,15 +212,26 @@ class BookShelf(Base): | ||||||
|     def __repr__(self): |     def __repr__(self): | ||||||
|         return '<Book %r>' % self.id |         return '<Book %r>' % self.id | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| class ReadBook(Base): | class ReadBook(Base): | ||||||
|     __tablename__ = 'book_read_link' |     __tablename__ = 'book_read_link' | ||||||
| 
 | 
 | ||||||
|     id=Column(Integer, primary_key=True) |     id = Column(Integer, primary_key=True) | ||||||
|     book_id = Column(Integer, unique=False) |     book_id = Column(Integer, unique=False) | ||||||
|     user_id =Column(Integer, ForeignKey('user.id'), unique=False) |     user_id = Column(Integer, ForeignKey('user.id'), unique=False) | ||||||
|     is_read = Column(Boolean, unique=False) |     is_read = Column(Boolean, unique=False) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | class Bookmark(Base): | ||||||
|  |     __tablename__ = 'bookmark' | ||||||
|  | 
 | ||||||
|  |     id = Column(Integer, primary_key=True) | ||||||
|  |     user_id = Column(Integer, ForeignKey('user.id')) | ||||||
|  |     book_id = Column(Integer) | ||||||
|  |     format = Column(String(collation='NOCASE')) | ||||||
|  |     bookmark_key = Column(String) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| # Baseclass representing Downloads from calibre-web in app.db | # Baseclass representing Downloads from calibre-web in app.db | ||||||
| class Downloads(Base): | class Downloads(Base): | ||||||
|     __tablename__ = 'downloads' |     __tablename__ = 'downloads' | ||||||
|  | @ -396,7 +407,9 @@ class Config: | ||||||
| # rows with SQL commands | # rows with SQL commands | ||||||
| def migrate_Database(): | def migrate_Database(): | ||||||
|     if not engine.dialect.has_table(engine.connect(), "book_read_link"): |     if not engine.dialect.has_table(engine.connect(), "book_read_link"): | ||||||
|         ReadBook.__table__.create(bind = engine) |         ReadBook.__table__.create(bind=engine) | ||||||
|  |     if not engine.dialect.has_table(engine.connect(), "bookmark"): | ||||||
|  |         Bookmark.__table__.create(bind=engine) | ||||||
| 
 | 
 | ||||||
|     try: |     try: | ||||||
|         session.query(exists().where(User.locale)).scalar() |         session.query(exists().where(User.locale)).scalar() | ||||||
|  |  | ||||||
							
								
								
									
										102
									
								
								cps/web.py
									
									
									
									
									
								
							
							
						
						
									
										102
									
								
								cps/web.py
									
									
									
									
									
								
							|  | @ -1354,6 +1354,26 @@ def show_book(book_id): | ||||||
|         return redirect(url_for("index")) |         return redirect(url_for("index")) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @app.route("/ajax/bookmark/<int:book_id>/<book_format>", methods=['POST']) | ||||||
|  | @login_required | ||||||
|  | def bookmark(book_id, book_format): | ||||||
|  |     bookmark_key = request.form["bookmark"] | ||||||
|  |     ub.session.query(ub.Bookmark).filter(ub.and_(ub.Bookmark.user_id == int(current_user.id), | ||||||
|  |                                                  ub.Bookmark.book_id == book_id, | ||||||
|  |                                                  ub.Bookmark.format == book_format)).delete() | ||||||
|  |     if not bookmark_key: | ||||||
|  |         ub.session.commit() | ||||||
|  |         return "", 204 | ||||||
|  | 
 | ||||||
|  |     bookmark = ub.Bookmark(user_id=current_user.id, | ||||||
|  |                            book_id=book_id, | ||||||
|  |                            format=book_format, | ||||||
|  |                            bookmark_key=bookmark_key) | ||||||
|  |     ub.session.merge(bookmark) | ||||||
|  |     ub.session.commit() | ||||||
|  |     return "", 201 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| @app.route("/admin") | @app.route("/admin") | ||||||
| @login_required | @login_required | ||||||
| def admin_forbidden(): | def admin_forbidden(): | ||||||
|  | @ -1794,49 +1814,51 @@ def unread_books(page): | ||||||
| @login_required_if_no_ano | @login_required_if_no_ano | ||||||
| def read_book(book_id, book_format): | def read_book(book_id, book_format): | ||||||
|     book = db.session.query(db.Books).filter(db.Books.id == book_id).first() |     book = db.session.query(db.Books).filter(db.Books.id == book_id).first() | ||||||
|     if book: |     if not book: | ||||||
|         book_dir = os.path.join(config.get_main_dir, "cps", "static", str(book_id)) |  | ||||||
|         if not os.path.exists(book_dir): |  | ||||||
|             os.mkdir(book_dir) |  | ||||||
|         if book_format.lower() == "epub": |  | ||||||
|             # check if mimetype file is exists |  | ||||||
|             mime_file = str(book_id) + "/mimetype" |  | ||||||
|             if not os.path.exists(mime_file): |  | ||||||
|                 epub_file = os.path.join(config.config_calibre_dir, book.path, book.data[0].name) + ".epub" |  | ||||||
|                 if not os.path.isfile(epub_file): |  | ||||||
|                     raise ValueError('Error opening eBook. File does not exist: ', epub_file) |  | ||||||
|                 zfile = zipfile.ZipFile(epub_file) |  | ||||||
|                 for name in zfile.namelist(): |  | ||||||
|                     (dirName, fileName) = os.path.split(name) |  | ||||||
|                     newDir = os.path.join(book_dir, dirName) |  | ||||||
|                     if not os.path.exists(newDir): |  | ||||||
|                         try: |  | ||||||
|                             os.makedirs(newDir) |  | ||||||
|                         except OSError as exception: |  | ||||||
|                             if not exception.errno == errno.EEXIST: |  | ||||||
|                                 raise |  | ||||||
|                     if fileName: |  | ||||||
|                         fd = open(os.path.join(newDir, fileName), "wb") |  | ||||||
|                         fd.write(zfile.read(name)) |  | ||||||
|                         fd.close() |  | ||||||
|                 zfile.close() |  | ||||||
|             return render_title_template('read.html', bookid=book_id, title=_(u"Read a Book")) |  | ||||||
|         elif book_format.lower() == "pdf": |  | ||||||
|             return render_title_template('readpdf.html', pdffile=book_id, title=_(u"Read a Book")) |  | ||||||
|         elif book_format.lower() == "txt": |  | ||||||
|             return render_title_template('readtxt.html', txtfile=book_id, title=_(u"Read a Book")) |  | ||||||
|         elif book_format.lower() == "cbr": |  | ||||||
|             all_name = str(book_id) + "/" + book.data[0].name + ".cbr" |  | ||||||
|             tmp_file = os.path.join(book_dir, book.data[0].name) + ".cbr" |  | ||||||
|             if not os.path.exists(all_name): |  | ||||||
|                 cbr_file = os.path.join(config.config_calibre_dir, book.path, book.data[0].name) + ".cbr" |  | ||||||
|                 copyfile(cbr_file, tmp_file) |  | ||||||
|             return render_title_template('readcbr.html', comicfile=all_name, title=_(u"Read a Book")) |  | ||||||
| 
 |  | ||||||
|     else: |  | ||||||
|         flash(_(u"Error opening eBook. File does not exist or file is not accessible:"), category="error") |         flash(_(u"Error opening eBook. File does not exist or file is not accessible:"), category="error") | ||||||
|         return redirect(url_for("index")) |         return redirect(url_for("index")) | ||||||
| 
 | 
 | ||||||
|  |     book_dir = os.path.join(config.get_main_dir, "cps", "static", str(book_id)) | ||||||
|  |     if not os.path.exists(book_dir): | ||||||
|  |         os.mkdir(book_dir) | ||||||
|  |     bookmark = ub.session.query(ub.Bookmark).filter(ub.and_(ub.Bookmark.user_id == int(current_user.id), | ||||||
|  |                                                             ub.Bookmark.book_id == book_id, | ||||||
|  |                                                             ub.Bookmark.format == book_format.upper())).first() | ||||||
|  |     if book_format.lower() == "epub": | ||||||
|  |         # check if mimetype file is exists | ||||||
|  |         mime_file = str(book_id) + "/mimetype" | ||||||
|  |         if not os.path.exists(mime_file): | ||||||
|  |             epub_file = os.path.join(config.config_calibre_dir, book.path, book.data[0].name) + ".epub" | ||||||
|  |             if not os.path.isfile(epub_file): | ||||||
|  |                 raise ValueError('Error opening eBook. File does not exist: ', epub_file) | ||||||
|  |             zfile = zipfile.ZipFile(epub_file) | ||||||
|  |             for name in zfile.namelist(): | ||||||
|  |                 (dirName, fileName) = os.path.split(name) | ||||||
|  |                 newDir = os.path.join(book_dir, dirName) | ||||||
|  |                 if not os.path.exists(newDir): | ||||||
|  |                     try: | ||||||
|  |                         os.makedirs(newDir) | ||||||
|  |                     except OSError as exception: | ||||||
|  |                         if not exception.errno == errno.EEXIST: | ||||||
|  |                             raise | ||||||
|  |                 if fileName: | ||||||
|  |                     fd = open(os.path.join(newDir, fileName), "wb") | ||||||
|  |                     fd.write(zfile.read(name)) | ||||||
|  |                     fd.close() | ||||||
|  |             zfile.close() | ||||||
|  |         return render_title_template('read.html', bookid=book_id, title=_(u"Read a Book"), bookmark=bookmark) | ||||||
|  |     elif book_format.lower() == "pdf": | ||||||
|  |         return render_title_template('readpdf.html', pdffile=book_id, title=_(u"Read a Book")) | ||||||
|  |     elif book_format.lower() == "txt": | ||||||
|  |         return render_title_template('readtxt.html', txtfile=book_id, title=_(u"Read a Book")) | ||||||
|  |     elif book_format.lower() == "cbr": | ||||||
|  |         all_name = str(book_id) + "/" + book.data[0].name + ".cbr" | ||||||
|  |         tmp_file = os.path.join(book_dir, book.data[0].name) + ".cbr" | ||||||
|  |         if not os.path.exists(all_name): | ||||||
|  |             cbr_file = os.path.join(config.config_calibre_dir, book.path, book.data[0].name) + ".cbr" | ||||||
|  |             copyfile(cbr_file, tmp_file) | ||||||
|  |         return render_title_template('readcbr.html', comicfile=all_name, title=_(u"Read a Book")) | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| @app.route("/download/<int:book_id>/<book_format>") | @app.route("/download/<int:book_id>/<book_format>") | ||||||
| @login_required_if_no_ano | @login_required_if_no_ano | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user