Merged master into 617 - fixed import copy conflict

pull/668/head
bodybybuddha 6 years ago
commit 1b363ac720

@ -123,9 +123,11 @@ def pdf_preview(tmp_file_path, tmp_dir):
def get_versions(): def get_versions():
if not use_generic_pdf_cover: if not use_generic_pdf_cover:
IVersion=ImageVersion.MAGICK_VERSION IVersion = ImageVersion.MAGICK_VERSION
WVersion = ImageVersion.VERSION
else: else:
IVersion = _(u'not installed') IVersion = _(u'not installed')
WVersion = _(u'not installed')
if use_pdf_meta: if use_pdf_meta:
PVersion='v'+PyPdfVersion PVersion='v'+PyPdfVersion
else: else:
@ -134,4 +136,4 @@ def get_versions():
XVersion = 'v'+'.'.join(map(str, lxmlversion)) XVersion = 'v'+'.'.join(map(str, lxmlversion))
else: else:
XVersion = _(u'not installed') XVersion = _(u'not installed')
return {'Image Magick': IVersion, 'PyPdf': PVersion, 'lxml':XVersion} return {'Image Magick': IVersion, 'PyPdf': PVersion, 'lxml':XVersion, 'Wand Version': WVersion}

@ -45,5 +45,5 @@ def versioncheck():
elif ub.config.config_ebookconverter == 2: elif ub.config.config_ebookconverter == 2:
return versionCalibre() return versionCalibre()
else: else:
return {'ebook_converter':''} return {'ebook_converter':_(u'not configured')}

@ -149,19 +149,19 @@ def getDrive(drive=None, gauth=None):
drive.auth.Refresh() drive.auth.Refresh()
return drive return drive
def listRootFolders(drive=None): def listRootFolders():
drive = getDrive(drive) drive = getDrive(Gdrive.Instance().drive)
folder = "'root' in parents and mimeType = 'application/vnd.google-apps.folder' and trashed = false" folder = "'root' in parents and mimeType = 'application/vnd.google-apps.folder' and trashed = false"
fileList = drive.ListFile({'q': folder}).GetList() fileList = drive.ListFile({'q': folder}).GetList()
return fileList return fileList
def getEbooksFolder(drive=None): def getEbooksFolder(drive):
return getFolderInFolder('root',config.config_google_drive_folder,drive) return getFolderInFolder('root',config.config_google_drive_folder,drive)
def getFolderInFolder(parentId, folderName,drive=None): def getFolderInFolder(parentId, folderName, drive):
drive = getDrive(drive) # drive = getDrive(drive)
query="" query=""
if folderName: if folderName:
query = "title = '%s' and " % folderName.replace("'", "\\'") query = "title = '%s' and " % folderName.replace("'", "\\'")
@ -190,7 +190,6 @@ def getEbooksFolderId(drive=None):
def getFile(pathId, fileName, drive): def getFile(pathId, fileName, drive):
# drive = getDrive(Gdrive.Instance().drive)
metaDataFile = "'%s' in parents and trashed = false and title = '%s'" % (pathId, fileName.replace("'", "\\'")) metaDataFile = "'%s' in parents and trashed = false and title = '%s'" % (pathId, fileName.replace("'", "\\'"))
fileList = drive.ListFile({'q': metaDataFile}).GetList() fileList = drive.ListFile({'q': metaDataFile}).GetList()
@ -200,8 +199,8 @@ def getFile(pathId, fileName, drive):
return fileList[0] return fileList[0]
def getFolderId(path, drive=None): def getFolderId(path, drive):
drive = getDrive(drive) # drive = getDrive(drive)
currentFolderId = getEbooksFolderId(drive) currentFolderId = getEbooksFolderId(drive)
sqlCheckPath = path if path[-1] == '/' else path + '/' sqlCheckPath = path if path[-1] == '/' else path + '/'
storedPathName = session.query(GdriveId).filter(GdriveId.path == sqlCheckPath).first() storedPathName = session.query(GdriveId).filter(GdriveId.path == sqlCheckPath).first()
@ -249,7 +248,7 @@ def getFileFromEbooksFolder(path, fileName):
return None return None
def copyDriveFileRemote(drive, origin_file_id, copy_title): '''def copyDriveFileRemote(drive, origin_file_id, copy_title):
drive = getDrive(drive) drive = getDrive(drive)
copied_file = {'title': copy_title} copied_file = {'title': copy_title}
try: try:
@ -258,7 +257,7 @@ def copyDriveFileRemote(drive, origin_file_id, copy_title):
return drive.CreateFile({'id': file_data['id']}) return drive.CreateFile({'id': file_data['id']})
except errors.HttpError as error: except errors.HttpError as error:
print ('An error occurred: %s' % error) print ('An error occurred: %s' % error)
return None return None'''
# Download metadata.db from gdrive # Download metadata.db from gdrive
@ -347,7 +346,6 @@ def uploadFileToEbooksFolder(destFile, f):
def watchChange(drive, channel_id, channel_type, channel_address, def watchChange(drive, channel_id, channel_type, channel_address,
channel_token=None, expiration=None): channel_token=None, expiration=None):
# drive = getDrive(drive)
# Watch for all changes to a user's Drive. # Watch for all changes to a user's Drive.
# Args: # Args:
# service: Drive API service instance. # service: Drive API service instance.
@ -390,8 +388,6 @@ def watchFile(drive, file_id, channel_id, channel_type, channel_address,
Raises: Raises:
apiclient.errors.HttpError: if http request to create channel fails. apiclient.errors.HttpError: if http request to create channel fails.
""" """
# drive = getDrive(drive)
body = { body = {
'id': channel_id, 'id': channel_id,
'type': channel_type, 'type': channel_type,
@ -413,8 +409,6 @@ def stopChannel(drive, channel_id, resource_id):
Raises: Raises:
apiclient.errors.HttpError: if http request to create channel fails. apiclient.errors.HttpError: if http request to create channel fails.
""" """
# drive = getDrive(drive)
# service=drive.auth.service
body = { body = {
'id': channel_id, 'id': channel_id,
'resourceId': resource_id 'resourceId': resource_id
@ -423,7 +417,6 @@ def stopChannel(drive, channel_id, resource_id):
def getChangeById (drive, change_id): def getChangeById (drive, change_id):
# drive = getDrive(drive)
# Print a single Change resource information. # Print a single Change resource information.
# #
# Args: # Args:
@ -454,11 +447,13 @@ def updateDatabaseOnEdit(ID,newPath):
storedPathName.path = newPath storedPathName.path = newPath
session.commit() session.commit()
# Deletes the hashes in database of deleted book # Deletes the hashes in database of deleted book
def deleteDatabaseEntry(ID): def deleteDatabaseEntry(ID):
session.query(GdriveId).filter(GdriveId.gdrive_id == ID).delete() session.query(GdriveId).filter(GdriveId.gdrive_id == ID).delete()
session.commit() session.commit()
# Gets cover file from gdrive # Gets cover file from gdrive
def get_cover_via_gdrive(cover_path): def get_cover_via_gdrive(cover_path):
df = getFileFromEbooksFolder(cover_path, 'cover.jpg') df = getFileFromEbooksFolder(cover_path, 'cover.jpg')

@ -0,0 +1,39 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
class ReverseProxied(object):
"""Wrap the application in this middleware and configure the
front-end server to add these headers, to let you quietly bind
this to a URL other than / and to an HTTP scheme that is
different than what is used locally.
Code courtesy of: http://flask.pocoo.org/snippets/35/
In nginx:
location /myprefix {
proxy_pass http://127.0.0.1:8083;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Scheme $scheme;
proxy_set_header X-Script-Name /myprefix;
}
"""
def __init__(self, application):
self.app = application
def __call__(self, environ, start_response):
script_name = environ.get('HTTP_X_SCRIPT_NAME', '')
if script_name:
environ['SCRIPT_NAME'] = script_name
path_info = environ.get('PATH_INFO', '')
if path_info and path_info.startswith(script_name):
environ['PATH_INFO'] = path_info[len(script_name):]
scheme = environ.get('HTTP_X_SCHEME', '')
if scheme:
environ['wsgi.url_scheme'] = scheme
servr = environ.get('HTTP_X_FORWARDED_SERVER', '')
if servr:
environ['HTTP_HOST'] = servr
return self.app(environ, start_response)

@ -1,11 +1,11 @@
#!/usr/bin/env python #!/usr/bin/env python
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from socket import error as SocketError from socket import error as SocketError
import sys import sys
import os import os
import signal import signal
import web
try: try:
from gevent.pywsgi import WSGIServer from gevent.pywsgi import WSGIServer
@ -19,8 +19,6 @@ except ImportError:
from tornado import version as tornadoVersion from tornado import version as tornadoVersion
gevent_present = False gevent_present = False
import web
class server: class server:
@ -68,7 +66,8 @@ class server:
ssl_options=ssl) ssl_options=ssl)
http_server.listen(web.ub.config.config_port) http_server.listen(web.ub.config.config_port)
self.wsgiserver=IOLoop.instance() self.wsgiserver=IOLoop.instance()
self.wsgiserver.start() # wait for stop signal self.wsgiserver.start()
# wait for stop signal
self.wsgiserver.close(True) self.wsgiserver.close(True)
if self.restart == True: if self.restart == True:

@ -1173,7 +1173,7 @@ msgstr "Pfad zu Konvertertool"
#: cps/templates/config_edit.html:199 #: cps/templates/config_edit.html:199
msgid "Location of Unrar binary" msgid "Location of Unrar binary"
msgstr "Ofad zum UnRar Programm" msgstr "Pfad zum UnRar Programm"
#: cps/templates/config_edit.html:215 cps/templates/layout.html:82 #: cps/templates/config_edit.html:215 cps/templates/layout.html:82
#: cps/templates/login.html:4 #: cps/templates/login.html:4

@ -1,38 +1,5 @@
#!/usr/bin/env python #!/usr/bin/env python
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
try:
from googleapiclient.errors import HttpError
except ImportError:
pass
try:
from goodreads.client import GoodreadsClient
goodreads_support = True
except ImportError:
goodreads_support = False
try:
import Levenshtein
levenshtein_support = True
except ImportError:
levenshtein_support = False
try:
from functools import reduce
except ImportError:
pass # We're not using Python 3
try:
import rarfile
rar_support=True
except ImportError:
rar_support=False
try:
from natsort import natsorted as sort
except ImportError:
sort=sorted # Just use regular sort then
# may cause issues with badly named pages in cbz/cbr files
import mimetypes import mimetypes
import logging import logging
@ -41,6 +8,8 @@ from flask import (Flask, render_template, request, Response, redirect,
url_for, send_from_directory, make_response, g, flash, url_for, send_from_directory, make_response, g, flash,
abort, Markup) abort, Markup)
from flask import __version__ as flaskVersion from flask import __version__ as flaskVersion
from werkzeug import __version__ as werkzeugVersion
from jinja2 import __version__ as jinja2Version
import cache_buster import cache_buster
import ub import ub
from ub import config from ub import config
@ -72,6 +41,7 @@ import json
import datetime import datetime
from iso639 import languages as isoLanguages from iso639 import languages as isoLanguages
from iso639 import __version__ as iso639Version from iso639 import __version__ as iso639Version
from pytz import __version__ as pytzVersion
from uuid import uuid4 from uuid import uuid4
import os.path import os.path
import sys import sys
@ -81,11 +51,44 @@ from shutil import move, copyfile
import gdriveutils import gdriveutils
import converter import converter
import tempfile import tempfile
import hashlib
from redirect import redirect_back from redirect import redirect_back
import time import time
import server import server
import copy import copy
from reverseproxy import ReverseProxied
try:
from googleapiclient.errors import HttpError
except ImportError:
pass
try:
from goodreads.client import GoodreadsClient
goodreads_support = True
except ImportError:
goodreads_support = False
try:
import Levenshtein
levenshtein_support = True
except ImportError:
levenshtein_support = False
try:
from functools import reduce
except ImportError:
pass # We're not using Python 3
try:
import rarfile
rar_support=True
except ImportError:
rar_support=False
try:
from natsort import natsorted as sort
except ImportError:
sort=sorted # Just use regular sort then
# may cause issues with badly named pages in cbz/cbr files
try: try:
import cPickle import cPickle
except ImportError: except ImportError:
@ -102,12 +105,10 @@ try:
except ImportError: except ImportError:
from flask_login.__about__ import __version__ as flask_loginVersion from flask_login.__about__ import __version__ as flask_loginVersion
current_milli_time = lambda: int(round(time.time() * 1000))
# Global variables # Global variables
current_milli_time = lambda: int(round(time.time() * 1000))
gdrive_watch_callback_token = 'target=calibreweb-watch_files' gdrive_watch_callback_token = 'target=calibreweb-watch_files'
EXTENSIONS_UPLOAD = {'txt', 'pdf', 'epub', 'mobi', 'azw', 'azw3', 'cbr', 'cbz', 'cbt', 'djvu', 'prc', 'doc', 'docx', EXTENSIONS_UPLOAD = {'txt', 'pdf', 'epub', 'mobi', 'azw', 'azw3', 'cbr', 'cbz', 'cbt', 'djvu', 'prc', 'doc', 'docx',
'fb2', 'html', 'rtf', 'odt'} 'fb2', 'html', 'rtf', 'odt'}
EXTENSIONS_CONVERT = {'pdf', 'epub', 'mobi', 'azw3', 'docx', 'rtf', 'fb2', 'lit', 'lrf', 'txt', 'html', 'rtf', 'odt'} EXTENSIONS_CONVERT = {'pdf', 'epub', 'mobi', 'azw3', 'docx', 'rtf', 'fb2', 'lit', 'lrf', 'txt', 'html', 'rtf', 'odt'}
@ -115,15 +116,7 @@ EXTENSIONS_CONVERT = {'pdf', 'epub', 'mobi', 'azw3', 'docx', 'rtf', 'fb2', 'lit'
# EXTENSIONS_READER = set(['txt', 'pdf', 'epub', 'zip', 'cbz', 'tar', 'cbt'] + (['rar','cbr'] if rar_support else [])) # EXTENSIONS_READER = set(['txt', 'pdf', 'epub', 'zip', 'cbz', 'tar', 'cbt'] + (['rar','cbr'] if rar_support else []))
def md5(fname): '''class ReverseProxied(object):
hash_md5 = hashlib.md5()
with open(fname, "rb") as f:
for chunk in iter(lambda: f.read(4096), b""):
hash_md5.update(chunk)
return hash_md5.hexdigest()
class ReverseProxied(object):
"""Wrap the application in this middleware and configure the """Wrap the application in this middleware and configure the
front-end server to add these headers, to let you quietly bind front-end server to add these headers, to let you quietly bind
this to a URL other than / and to an HTTP scheme that is this to a URL other than / and to an HTTP scheme that is
@ -158,7 +151,7 @@ class ReverseProxied(object):
servr = environ.get('HTTP_X_FORWARDED_SERVER', '') servr = environ.get('HTTP_X_FORWARDED_SERVER', '')
if servr: if servr:
environ['HTTP_HOST'] = servr environ['HTTP_HOST'] = servr
return self.app(environ, start_response) return self.app(environ, start_response)'''
# Main code # Main code
@ -1674,15 +1667,19 @@ def stats():
categorys = db.session.query(db.Tags).count() categorys = db.session.query(db.Tags).count()
series = db.session.query(db.Series).count() series = db.session.query(db.Series).count()
versions = uploader.book_formats.get_versions() versions = uploader.book_formats.get_versions()
versions['Babel'] = 'v'+babelVersion versions['Babel'] = 'v' + babelVersion
versions['Sqlalchemy'] = 'v'+sqlalchemyVersion versions['Sqlalchemy'] = 'v' + sqlalchemyVersion
versions['Flask'] = 'v'+flaskVersion versions['Werkzeug'] = 'v' + werkzeugVersion
versions['Flask Login'] = 'v'+flask_loginVersion versions['Jinja2'] = 'v' + jinja2Version
versions['Flask Principal'] = 'v'+flask_principalVersion versions['Flask'] = 'v' + flaskVersion
versions['Iso 639'] = 'v'+iso639Version versions['Flask Login'] = 'v' + flask_loginVersion
versions['Requests'] = 'v'+requests.__version__ versions['Flask Principal'] = 'v' + flask_principalVersion
versions['pySqlite'] = 'v'+db.engine.dialect.dbapi.version versions['Iso 639'] = 'v' + iso639Version
versions['Sqlite'] = 'v'+db.engine.dialect.dbapi.sqlite_version versions['pytz'] = 'v' + pytzVersion
versions['Requests'] = 'v' + requests.__version__
versions['pySqlite'] = 'v' + db.engine.dialect.dbapi.version
versions['Sqlite'] = 'v' + db.engine.dialect.dbapi.sqlite_version
versions.update(converter.versioncheck()) versions.update(converter.versioncheck())
versions.update(server.Server.getNameVersion()) versions.update(server.Server.getNameVersion())
versions['Python'] = sys.version versions['Python'] = sys.version
@ -3367,24 +3364,19 @@ def reset_password(user_id):
return redirect(url_for('admin')) return redirect(url_for('admin'))
@app.route("/admin/book/<int:book_id>", methods=['GET', 'POST']) def render_edit_book(book_id):
@login_required_if_no_ano
@edit_required
def edit_book(book_id):
# create the function for sorting...
db.session.connection().connection.connection.create_function("title_sort", 1, db.title_sort) db.session.connection().connection.connection.create_function("title_sort", 1, db.title_sort)
cc = db.session.query(db.Custom_Columns).filter(db.Custom_Columns.datatype.notin_(db.cc_exceptions)).all() cc = db.session.query(db.Custom_Columns).filter(db.Custom_Columns.datatype.notin_(db.cc_exceptions)).all()
book = db.session.query(db.Books)\ book = db.session.query(db.Books)\
.filter(db.Books.id == book_id).filter(common_filters()).first() .filter(db.Books.id == book_id).filter(common_filters()).first()
author_names = []
# Book not found
if not book: if not book:
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"))
for indx in range(0, len(book.languages)): for indx in range(0, len(book.languages)):
book.languages[indx].language_name = language_table[get_locale()][book.languages[indx].lang_code] book.languages[indx].language_name = language_table[get_locale()][book.languages[indx].lang_code]
author_names = []
for authr in book.authors: for authr in book.authors:
author_names.append(authr.name.replace('|', ',')) author_names.append(authr.name.replace('|', ','))
@ -3403,14 +3395,92 @@ def edit_book(book_id):
except Exception: except Exception:
app.logger.warning(file.format.lower() + ' already removed from list.') app.logger.warning(file.format.lower() + ' already removed from list.')
app.logger.debug('Allowed conversion formats: '+ ', '.join(allowed_conversion_formats)) return render_title_template('book_edit.html', book=book, authors=author_names, cc=cc,
title=_(u"edit metadata"), page="editbook",
conversion_formats=allowed_conversion_formats,
source_formats=valid_source_formats)
# Show form
if request.method != 'POST': def edit_cc_data(book_id, book, to_save):
return render_title_template('book_edit.html', book=book, authors=author_names, cc=cc, cc = db.session.query(db.Custom_Columns).filter(db.Custom_Columns.datatype.notin_(db.cc_exceptions)).all()
title=_(u"edit metadata"), page="editbook", for c in cc:
conversion_formats=allowed_conversion_formats, cc_string = "custom_column_" + str(c.id)
source_formats=valid_source_formats) if not c.is_multiple:
if len(getattr(book, cc_string)) > 0:
cc_db_value = getattr(book, cc_string)[0].value
else:
cc_db_value = None
if to_save[cc_string].strip():
if c.datatype == 'bool':
if to_save[cc_string] == 'None':
to_save[cc_string] = None
else:
to_save[cc_string] = 1 if to_save[cc_string] == 'True' else 0
if to_save[cc_string] != cc_db_value:
if cc_db_value is not None:
if to_save[cc_string] is not None:
setattr(getattr(book, cc_string)[0], 'value', to_save[cc_string])
else:
del_cc = getattr(book, cc_string)[0]
getattr(book, cc_string).remove(del_cc)
db.session.delete(del_cc)
else:
cc_class = db.cc_classes[c.id]
new_cc = cc_class(value=to_save[cc_string], book=book_id)
db.session.add(new_cc)
elif c.datatype == 'int':
if to_save[cc_string] == 'None':
to_save[cc_string] = None
if to_save[cc_string] != cc_db_value:
if cc_db_value is not None:
if to_save[cc_string] is not None:
setattr(getattr(book, cc_string)[0], 'value', to_save[cc_string])
else:
del_cc = getattr(book, cc_string)[0]
getattr(book, cc_string).remove(del_cc)
db.session.delete(del_cc)
else:
cc_class = db.cc_classes[c.id]
new_cc = cc_class(value=to_save[cc_string], book=book_id)
db.session.add(new_cc)
else:
if c.datatype == 'rating':
to_save[cc_string] = str(int(float(to_save[cc_string]) * 2))
if to_save[cc_string].strip() != cc_db_value:
if cc_db_value is not None:
# remove old cc_val
del_cc = getattr(book, cc_string)[0]
getattr(book, cc_string).remove(del_cc)
if len(del_cc.books) == 0:
db.session.delete(del_cc)
cc_class = db.cc_classes[c.id]
new_cc = db.session.query(cc_class).filter(
cc_class.value == to_save[cc_string].strip()).first()
# if no cc val is found add it
if new_cc is None:
new_cc = cc_class(value=to_save[cc_string].strip())
db.session.add(new_cc)
db.session.flush()
new_cc = db.session.query(cc_class).filter(
cc_class.value == to_save[cc_string].strip()).first()
# add cc value to book
getattr(book, cc_string).append(new_cc)
else:
if cc_db_value is not None:
# remove old cc_val
del_cc = getattr(book, cc_string)[0]
getattr(book, cc_string).remove(del_cc)
if len(del_cc.books) == 0:
db.session.delete(del_cc)
else:
input_tags = to_save[cc_string].split(',')
input_tags = list(map(lambda it: it.strip(), input_tags))
modify_database_object(input_tags, getattr(book, cc_string), db.cc_classes[c.id], db.session,
'custom')
return cc
def upload_single_file(request, book, book_id):
# Check and handle Uploaded file # Check and handle Uploaded file
if 'btn-upload-format' in request.files: if 'btn-upload-format' in request.files:
requested_file = request.files['btn-upload-format'] requested_file = request.files['btn-upload-format']
@ -3460,6 +3530,7 @@ def edit_book(book_id):
helper.global_WorkerThread.add_upload(current_user.nickname, helper.global_WorkerThread.add_upload(current_user.nickname,
"<a href=\"" + url_for('show_book', book_id=book.id) + "\">" + uploadText + "</a>") "<a href=\"" + url_for('show_book', book_id=book.id) + "\">" + uploadText + "</a>")
def upload_cover(request, book):
if 'btn-upload-cover' in request.files: if 'btn-upload-cover' in request.files:
requested_file = request.files['btn-upload-cover'] requested_file = request.files['btn-upload-cover']
# check for empty request # check for empty request
@ -3485,15 +3556,37 @@ def edit_book(book_id):
except IOError: except IOError:
flash(_(u"Cover-file is not a valid image file" % saved_filename), category="error") flash(_(u"Cover-file is not a valid image file" % saved_filename), category="error")
return redirect(url_for('show_book', book_id=book.id)) return redirect(url_for('show_book', book_id=book.id))
to_save = request.form.to_dict()
@app.route("/admin/book/<int:book_id>", methods=['GET', 'POST'])
@login_required_if_no_ano
@edit_required
def edit_book(book_id):
# Show form
if request.method != 'POST':
return render_edit_book(book_id)
# create the function for sorting...
db.session.connection().connection.connection.create_function("title_sort", 1, db.title_sort)
book = db.session.query(db.Books)\
.filter(db.Books.id == book_id).filter(common_filters()).first()
# Book not found
if not book:
flash(_(u"Error opening eBook. File does not exist or file is not accessible"), category="error")
return redirect(url_for("index"))
upload_single_file(request, book, book_id)
upload_cover(request, book)
try: try:
to_save = request.form.to_dict()
# Update book # Update book
edited_books_id = set() edited_books_id = None
#handle book title #handle book title
if book.title != to_save["book_title"]: if book.title != to_save["book_title"]:
if to_save["book_title"] == '':
to_save["book_title"] = _(u'unknown')
book.title = to_save["book_title"] book.title = to_save["book_title"]
edited_books_id.add(book.id) edited_books_id = book.id
# handle author(s) # handle author(s)
input_authors = to_save["author_name"].split('&') input_authors = to_save["author_name"].split('&')
@ -3508,18 +3601,17 @@ def edit_book(book_id):
modify_database_object(input_authors, book.authors, db.Authors, db.session, 'author') modify_database_object(input_authors, book.authors, db.Authors, db.session, 'author')
if book.authors: if book.authors:
if author0_before_edit != book.authors[0].name: if author0_before_edit != book.authors[0].name:
edited_books_id.add(book.id) edited_books_id = book.id
book.author_sort = helper.get_sorted_author(input_authors[0]) book.author_sort = helper.get_sorted_author(input_authors[0])
if config.config_use_google_drive: if config.config_use_google_drive:
gdriveutils.updateGdriveCalibreFromLocal() gdriveutils.updateGdriveCalibreFromLocal()
error = False error = False
for b in edited_books_id: if edited_books_id:
error = helper.update_dir_stucture(b, config.config_calibre_dir) error = helper.update_dir_stucture(edited_books_id, config.config_calibre_dir)
if error: # stop on error if error: # stop on error
flash(error, category="error") flash(error, category="error")
break
if not error: if not error:
if to_save["cover_url"]: if to_save["cover_url"]:
@ -3562,7 +3654,6 @@ def edit_book(book_id):
# handle book languages # handle book languages
input_languages = to_save["languages"].split(',') input_languages = to_save["languages"].split(',')
# input_languages = list(map(lambda it: it.strip().lower(), input_languages))
input_languages = [x.strip().lower() for x in input_languages if x != ''] input_languages = [x.strip().lower() for x in input_languages if x != '']
input_l = [] input_l = []
invers_lang_table = [x.lower() for x in language_table[get_locale()].values()] invers_lang_table = [x.lower() for x in language_table[get_locale()].values()]
@ -3575,6 +3666,7 @@ def edit_book(book_id):
flash(_(u"%(langname)s is not a valid language", langname=lang), category="error") flash(_(u"%(langname)s is not a valid language", langname=lang), category="error")
modify_database_object(input_l, book.languages, db.Languages, db.session, 'languages') modify_database_object(input_l, book.languages, db.Languages, db.session, 'languages')
# handle book ratings
if to_save["rating"].strip(): if to_save["rating"].strip():
old_rating = False old_rating = False
if len(book.ratings) > 0: if len(book.ratings) > 0:
@ -3593,104 +3685,20 @@ def edit_book(book_id):
if len(book.ratings) > 0: if len(book.ratings) > 0:
book.ratings.remove(book.ratings[0]) book.ratings.remove(book.ratings[0])
for c in cc: # handle cc data
cc_string = "custom_column_" + str(c.id) edit_cc_data(book_id, book, to_save)
if not c.is_multiple:
if len(getattr(book, cc_string)) > 0:
cc_db_value = getattr(book, cc_string)[0].value
else:
cc_db_value = None
if to_save[cc_string].strip():
if c.datatype == 'bool':
if to_save[cc_string] == 'None':
to_save[cc_string] = None
else:
to_save[cc_string] = 1 if to_save[cc_string] == 'True' else 0
if to_save[cc_string] != cc_db_value:
if cc_db_value is not None:
if to_save[cc_string] is not None:
setattr(getattr(book, cc_string)[0], 'value', to_save[cc_string])
else:
del_cc = getattr(book, cc_string)[0]
getattr(book, cc_string).remove(del_cc)
db.session.delete(del_cc)
else:
cc_class = db.cc_classes[c.id]
new_cc = cc_class(value=to_save[cc_string], book=book_id)
db.session.add(new_cc)
elif c.datatype == 'int':
if to_save[cc_string] == 'None':
to_save[cc_string] = None
if to_save[cc_string] != cc_db_value:
if cc_db_value is not None:
if to_save[cc_string] is not None:
setattr(getattr(book, cc_string)[0], 'value', to_save[cc_string])
else:
del_cc = getattr(book, cc_string)[0]
getattr(book, cc_string).remove(del_cc)
db.session.delete(del_cc)
else:
cc_class = db.cc_classes[c.id]
new_cc = cc_class(value=to_save[cc_string], book=book_id)
db.session.add(new_cc)
else:
if c.datatype == 'rating':
to_save[cc_string] = str(int(float(to_save[cc_string]) * 2))
if to_save[cc_string].strip() != cc_db_value:
if cc_db_value is not None:
# remove old cc_val
del_cc = getattr(book, cc_string)[0]
getattr(book, cc_string).remove(del_cc)
if len(del_cc.books) == 0:
db.session.delete(del_cc)
cc_class = db.cc_classes[c.id]
new_cc = db.session.query(cc_class).filter(
cc_class.value == to_save[cc_string].strip()).first()
# if no cc val is found add it
if new_cc is None:
new_cc = cc_class(value=to_save[cc_string].strip())
db.session.add(new_cc)
db.session.flush()
new_cc = db.session.query(cc_class).filter(
cc_class.value == to_save[cc_string].strip()).first()
# add cc value to book
getattr(book, cc_string).append(new_cc)
else:
if cc_db_value is not None:
# remove old cc_val
del_cc = getattr(book, cc_string)[0]
getattr(book, cc_string).remove(del_cc)
if len(del_cc.books) == 0:
db.session.delete(del_cc)
else:
input_tags = to_save[cc_string].split(',')
input_tags = list(map(lambda it: it.strip(), input_tags))
modify_database_object(input_tags, getattr(book, cc_string), db.cc_classes[c.id], db.session,
'custom')
db.session.commit() db.session.commit()
if config.config_use_google_drive: if config.config_use_google_drive:
gdriveutils.updateGdriveCalibreFromLocal() gdriveutils.updateGdriveCalibreFromLocal()
if "detail_view" in to_save: if "detail_view" in to_save:
return redirect(url_for('show_book', book_id=book.id)) return redirect(url_for('show_book', book_id=book.id))
else: else:
for indx in range(0, len(book.languages)): return render_edit_book(book_id)
try:
book.languages[indx].language_name = LC.parse(book.languages[indx].lang_code).get_language_name(
get_locale())
except UnknownLocaleError:
book.languages[indx].language_name = _(
isoLanguages.get(part3=book.languages[indx].lang_code).name)
author_names = []
for authr in book.authors:
author_names.append(authr.name)
return render_title_template('book_edit.html', book=book, authors=author_names, cc=cc,
title=_(u"edit metadata"), page="editbook")
else: else:
db.session.rollback() db.session.rollback()
flash(error, category="error") flash(error, category="error")
return render_title_template('book_edit.html', book=book, authors=author_names, cc=cc, return render_edit_book(book_id)
title=_(u"edit metadata"), page="editbook")
except Exception as e: except Exception as e:
app.logger.exception(e) app.logger.exception(e)
db.session.rollback() db.session.rollback()

Loading…
Cancel
Save