diff --git a/cps/db.py b/cps/db.py index 2dfd92c1..61a426f0 100644 --- a/cps/db.py +++ b/cps/db.py @@ -340,7 +340,7 @@ class Books(Base): self.series_index = series_index self.last_modified = last_modified self.path = path - self.has_cover = has_cover + self.has_cover = (has_cover != None) #def as_dict(self): # return {c.name: getattr(self, c.name) for c in self.__table__.columns} diff --git a/cps/editbooks.py b/cps/editbooks.py index 0c5f5889..84a24ca5 100644 --- a/cps/editbooks.py +++ b/cps/editbooks.py @@ -598,6 +598,7 @@ def edit_book(book_id): merge_metadata(to_save, meta) # Update book edited_books_id = None + #handle book title if book.title != to_save["book_title"].rstrip().strip(): if to_save["book_title"] == '': @@ -805,42 +806,17 @@ def upload(): if not db_author: db_author = stored_author sort_author = stored_author.sort - sort_authors_list.append(sort_author) # helper.get_sorted_author(sort_author)) + sort_authors_list.append(sort_author) sort_authors = ' & '.join(sort_authors_list) title_dir = helper.get_valid_filename(title) author_dir = helper.get_valid_filename(db_author.name) - filepath = os.path.join(config.config_calibre_dir, author_dir, title_dir) - saved_filename = os.path.join(filepath, title_dir + meta.extension.lower()) - - # check if file path exists, otherwise create it, copy file to calibre path and delete temp file - if not os.path.exists(filepath): - try: - os.makedirs(filepath) - except OSError: - log.error("Failed to create path %s (Permission denied)", filepath) - flash(_(u"Failed to create path %(path)s (Permission denied).", path=filepath), category="error") - return Response(json.dumps({"location": url_for("web.index")}), mimetype='application/json') - try: - copyfile(meta.file_path, saved_filename) - os.unlink(meta.file_path) - except OSError as e: - log.error("Failed to move file %s: %s", saved_filename, e) - flash(_(u"Failed to Move File %(file)s: %(error)s", file=saved_filename, error=e), category="error") - return Response(json.dumps({"location": url_for("web.index")}), mimetype='application/json') - - if meta.cover is None: - has_cover = 0 - copyfile(os.path.join(constants.STATIC_DIR, 'generic_cover.jpg'), - os.path.join(filepath, "cover.jpg")) - else: - has_cover = 1 # combine path and normalize path from windows systems path = os.path.join(author_dir, title_dir).replace('\\', '/') # Calibre adds books with utc as timezone db_book = db.Books(title, "", sort_authors, datetime.utcnow(), datetime(101, 1, 1), - '1', datetime.utcnow(), path, has_cover, db_author, [], "") + '1', datetime.utcnow(), path, meta.cover, db_author, [], "") modif_date |= modify_database_object(input_authors, db_book.authors, db.Authors, calibre_db.session, 'author') @@ -858,7 +834,7 @@ def upload(): modif_date |= edit_book_series(meta.series, db_book) # Add file to book - file_size = os.path.getsize(saved_filename) + file_size = os.path.getsize(meta.file_path) db_data = db.Data(db_book, meta.extension.upper()[1:], file_size, title_dir) db_book.data.append(db_data) calibre_db.session.add(db_book) @@ -866,25 +842,32 @@ def upload(): # flush content, get db_book.id available calibre_db.session.flush() - # Comments needs book id therfore only possiblw after flush + # Comments needs book id therfore only possible after flush modif_date |= edit_book_comments(Markup(meta.description).unescape(), db_book) book_id = db_book.id title = db_book.title - error = helper.update_dir_stucture(book_id, config.config_calibre_dir, input_authors[0]) + error = helper.update_dir_stucture(book_id, + config.config_calibre_dir, + input_authors[0], + meta.file_path, + title_dir + meta.extension) # move cover to final directory, including book id - if has_cover: - new_coverpath = os.path.join(config.config_calibre_dir, db_book.path, "cover.jpg") - try: - copyfile(meta.cover, new_coverpath) - os.unlink(meta.cover) - except OSError as e: - log.error("Failed to move cover file %s: %s", new_coverpath, e) - flash(_(u"Failed to Move Cover File %(file)s: %(error)s", file=new_coverpath, - error=e), - category="error") + if meta.cover: + coverfile = meta.cover + else: + coverfile = os.path.join(constants.STATIC_DIR, 'generic_cover.jpg') + new_coverpath = os.path.join(config.config_calibre_dir, db_book.path, "cover.jpg") + try: + copyfile(coverfile, new_coverpath) + os.unlink(meta.cover) + except OSError as e: + log.error("Failed to move cover file %s: %s", new_coverpath, e) + flash(_(u"Failed to Move Cover File %(file)s: %(error)s", file=new_coverpath, + error=e), + category="error") # save data to database, reread data calibre_db.session.commit() diff --git a/cps/helper.py b/cps/helper.py index c2fc3ec0..7f7bb4a3 100644 --- a/cps/helper.py +++ b/cps/helper.py @@ -351,67 +351,70 @@ def delete_book_file(book, calibrepath, book_format=None): path=book.path) -def update_dir_structure_file(book_id, calibrepath, first_author): +# Moves files in file storage during author/title rename, or from temp dir to file storage +def update_dir_structure_file(book_id, calibrepath, first_author, orignal_filepath, db_filename): + # get book database entry from id, if original path overwrite source with original_filepath localbook = calibre_db.get_book(book_id) - path = os.path.join(calibrepath, localbook.path) + if orignal_filepath: + path = orignal_filepath + else: + path = os.path.join(calibrepath, localbook.path) + # Create (current) authordir and titledir from database authordir = localbook.path.split('/')[0] + titledir = localbook.path.split('/')[1] + + # Create new_authordir from parameter or from database + # Create new titledir from database and add id if first_author: new_authordir = get_valid_filename(first_author) else: new_authordir = get_valid_filename(localbook.authors[0].name) - - titledir = localbook.path.split('/')[1] new_titledir = get_valid_filename(localbook.title) + " (" + str(book_id) + ")" - if titledir != new_titledir: - new_title_path = os.path.join(os.path.dirname(path), new_titledir) + if titledir != new_titledir or authordir != new_authordir or orignal_filepath: + new_path = os.path.join(calibrepath, new_authordir, new_titledir) + new_name = get_valid_filename(localbook.title) + ' - ' + get_valid_filename(new_authordir) try: - if not os.path.exists(new_title_path): - os.renames(os.path.normcase(path), os.path.normcase(new_title_path)) - else: - log.info("Copying title: %s into existing: %s", path, new_title_path) + if orignal_filepath: + os.renames(os.path.normcase(path), + os.path.normcase(os.path.join(new_path, db_filename))) + log.debug("Moving title: %s to %s/%s", path, new_path, new_name) + # Check new path is not valid path + elif not os.path.exists(new_path): + # move original path to new path + os.renames(os.path.normcase(path), os.path.normcase(new_path)) + log.debug("Moving title: %s to %s", path, new_path) + else: # path is valid copy only files to new location (merge) + log.info("Moving title: %s into existing: %s", path, new_path) + # Take all files and subfolder from old path (strange command) for dir_name, __, file_list in os.walk(path): for file in file_list: os.renames(os.path.normcase(os.path.join(dir_name, file)), - os.path.normcase(os.path.join(new_title_path + dir_name[len(path):], file))) - path = new_title_path - localbook.path = localbook.path.split('/')[0] + '/' + new_titledir + os.path.normcase(os.path.join(new_path + dir_name[len(path):], file))) + # change location in database to new author/title path + localbook.path = os.path.join(new_authordir, new_titledir) except OSError as ex: - log.error("Rename title from: %s to %s: %s", path, new_title_path, ex) + log.error("Rename title from: %s to %s: %s", path, new_path, ex) log.debug(ex, exc_info=True) return _("Rename title from: '%(src)s' to '%(dest)s' failed with error: %(error)s", - src=path, dest=new_title_path, error=str(ex)) - if authordir != new_authordir: - new_author_path = os.path.join(calibrepath, new_authordir, os.path.basename(path)) + src=path, dest=new_path, error=str(ex)) + + # Rename all files from old names to new names try: - os.renames(os.path.normcase(path), os.path.normcase(new_author_path)) - localbook.path = new_authordir + '/' + localbook.path.split('/')[1] - except OSError as ex: - log.error("Rename author from: %s to %s: %s", path, new_author_path, ex) - log.debug(ex, exc_info=True) - return _("Rename author from: '%(src)s' to '%(dest)s' failed with error: %(error)s", - src=path, dest=new_author_path, error=str(ex)) - # Rename all files from old names to new names - if authordir != new_authordir or titledir != new_titledir: - new_name = "" - try: - new_name = get_valid_filename(localbook.title) + ' - ' + get_valid_filename(new_authordir) - path_name = os.path.join(calibrepath, new_authordir, os.path.basename(path)) for file_format in localbook.data: os.renames(os.path.normcase( - os.path.join(path_name, file_format.name + '.' + file_format.format.lower())), - os.path.normcase(os.path.join(path_name, new_name + '.' + file_format.format.lower()))) + os.path.join(new_path, file_format.name + '.' + file_format.format.lower())), + os.path.normcase(os.path.join(new_path, new_name + '.' + file_format.format.lower()))) file_format.name = new_name except OSError as ex: - log.error("Rename file in path %s to %s: %s", path, new_name, ex) + log.error("Rename file in path %s to %s: %s", new_path, new_name, ex) log.debug(ex, exc_info=True) return _("Rename file in path '%(src)s' to '%(dest)s' failed with error: %(error)s", - src=path, dest=new_name, error=str(ex)) + src=new_path, dest=new_name, error=str(ex)) return False - -def update_dir_structure_gdrive(book_id, first_author): +def update_dir_structure_gdrive(book_id, first_author, original_filepath): error = False book = calibre_db.get_book(book_id) path = book.path @@ -513,11 +516,11 @@ def uniq(inpt): # ################################# External interface ################################# -def update_dir_stucture(book_id, calibrepath, first_author=None): +def update_dir_stucture(book_id, calibrepath, first_author=None, orignal_filepath=None, db_filename=None): if config.config_use_google_drive: - return update_dir_structure_gdrive(book_id, first_author) + return update_dir_structure_gdrive(book_id, first_author, orignal_filepath, db_filename) else: - return update_dir_structure_file(book_id, calibrepath, first_author) + return update_dir_structure_file(book_id, calibrepath, first_author, orignal_filepath, db_filename) def delete_book(book, calibrepath, book_format):