mirror of
https://github.com/janeczku/calibre-web
synced 2024-11-28 04:19:59 +00:00
Fix for #1407 converting books should now be possible again
This commit is contained in:
parent
a48418364c
commit
1a458fe39f
@ -37,6 +37,9 @@ from . import config_sql, logger, cache_buster, cli, ub, db
|
||||
from .reverseproxy import ReverseProxied
|
||||
from .server import WebServer
|
||||
|
||||
# import queue
|
||||
# queue = queue.Queue()
|
||||
|
||||
mimetypes.init()
|
||||
mimetypes.add_type('application/xhtml+xml', '.xhtml')
|
||||
mimetypes.add_type('application/epub+zip', '.epub')
|
||||
@ -82,6 +85,8 @@ log = logger.create()
|
||||
|
||||
from . import services
|
||||
|
||||
calibre_db = db.CalibreDB()
|
||||
|
||||
def create_app():
|
||||
app.wsgi_app = ReverseProxied(app.wsgi_app)
|
||||
# For python2 convert path to unicode
|
||||
@ -98,7 +103,8 @@ def create_app():
|
||||
app.secret_key = os.getenv('SECRET_KEY', config_sql.get_flask_session_key(ub.session))
|
||||
|
||||
web_server.init_app(app, config)
|
||||
db.setup_db(config, cli.settingspath)
|
||||
calibre_db.setup_db(config, cli.settingspath)
|
||||
calibre_db.start()
|
||||
|
||||
babel.init_app(app)
|
||||
_BABEL_TRANSLATIONS.update(str(item) for item in babel.list_translations())
|
||||
|
10
cps/about.py
10
cps/about.py
@ -30,7 +30,7 @@ import babel, pytz, requests, sqlalchemy
|
||||
import werkzeug, flask, flask_login, flask_principal, jinja2
|
||||
from flask_babel import gettext as _
|
||||
|
||||
from . import db, converter, uploader, server, isoLanguages, constants
|
||||
from . import db, calibre_db, converter, uploader, server, isoLanguages, constants
|
||||
from .web import render_title_template
|
||||
try:
|
||||
from flask_login import __version__ as flask_loginVersion
|
||||
@ -85,10 +85,10 @@ _VERSIONS.update(uploader.get_versions())
|
||||
@about.route("/stats")
|
||||
@flask_login.login_required
|
||||
def stats():
|
||||
counter = db.session.query(db.Books).count()
|
||||
authors = db.session.query(db.Authors).count()
|
||||
categorys = db.session.query(db.Tags).count()
|
||||
series = db.session.query(db.Series).count()
|
||||
counter = calibre_db.session.query(db.Books).count()
|
||||
authors = calibre_db.session.query(db.Authors).count()
|
||||
categorys = calibre_db.session.query(db.Tags).count()
|
||||
series = calibre_db.session.query(db.Series).count()
|
||||
_VERSIONS['ebook converter'] = _(converter.get_calibre_version())
|
||||
_VERSIONS['unrar'] = _(converter.get_unrar_version())
|
||||
_VERSIONS['kepubify'] = _(converter.get_kepubify_version())
|
||||
|
12
cps/admin.py
12
cps/admin.py
@ -38,7 +38,7 @@ from sqlalchemy.exc import IntegrityError
|
||||
from sqlalchemy.sql.expression import func
|
||||
|
||||
from . import constants, logger, helper, services
|
||||
from . import db, ub, web_server, get_locale, config, updater_thread, babel, gdriveutils
|
||||
from . import db, calibre_db, ub, web_server, get_locale, config, updater_thread, babel, gdriveutils
|
||||
from .helper import speaking_language, check_valid_domain, send_test_mail, reset_password, generate_password_hash
|
||||
from .gdriveutils import is_gdrive_ready, gdrive_support
|
||||
from .web import admin_required, render_title_template, before_request, unconfigured, login_required_if_no_ano
|
||||
@ -86,7 +86,7 @@ def shutdown():
|
||||
showtext = {}
|
||||
if task in (0, 1): # valid commandos received
|
||||
# close all database connections
|
||||
db.dispose()
|
||||
calibre_db.dispose()
|
||||
ub.dispose()
|
||||
|
||||
if task == 0:
|
||||
@ -99,7 +99,7 @@ def shutdown():
|
||||
|
||||
if task == 2:
|
||||
log.warning("reconnecting to calibre database")
|
||||
db.setup_db(config, ub.app_DB_path)
|
||||
calibre_db.setup_db(config, ub.app_DB_path)
|
||||
showtext['text'] = _(u'Reconnect successful')
|
||||
return json.dumps(showtext)
|
||||
|
||||
@ -148,9 +148,9 @@ def configuration():
|
||||
@login_required
|
||||
@admin_required
|
||||
def view_configuration():
|
||||
readColumn = db.session.query(db.Custom_Columns)\
|
||||
readColumn = calibre_db.session.query(db.Custom_Columns)\
|
||||
.filter(and_(db.Custom_Columns.datatype == 'bool',db.Custom_Columns.mark_for_delete == 0)).all()
|
||||
restrictColumns= db.session.query(db.Custom_Columns)\
|
||||
restrictColumns= calibre_db.session.query(db.Custom_Columns)\
|
||||
.filter(and_(db.Custom_Columns.datatype == 'text',db.Custom_Columns.mark_for_delete == 0)).all()
|
||||
return render_title_template("config_view_edit.html", conf=config, readColumns=readColumn,
|
||||
restrictColumns=restrictColumns,
|
||||
@ -944,7 +944,7 @@ def edit_user(user_id):
|
||||
translations = babel.list_translations() + [LC('en')]
|
||||
kobo_support = feature_support['kobo'] and config.config_kobo_sync
|
||||
for book in content.downloads:
|
||||
downloadbook = db.session.query(db.Books).filter(db.Books.id == book.book_id).first()
|
||||
downloadbook = calibre_db.session.query(db.Books).filter(db.Books.id == book.book_id).first()
|
||||
if downloadbook:
|
||||
downloads.append(downloadbook)
|
||||
else:
|
||||
|
283
cps/db.py
Executable file → Normal file
283
cps/db.py
Executable file → Normal file
@ -23,18 +23,22 @@ import os
|
||||
import re
|
||||
import ast
|
||||
from datetime import datetime
|
||||
import threading
|
||||
import time
|
||||
import queue
|
||||
|
||||
from sqlalchemy import create_engine, event
|
||||
from sqlalchemy import create_engine
|
||||
from sqlalchemy import Table, Column, ForeignKey, CheckConstraint
|
||||
from sqlalchemy import String, Integer, Boolean, TIMESTAMP, Float
|
||||
from sqlalchemy.orm import relationship, sessionmaker, scoped_session
|
||||
from sqlalchemy.ext.declarative import declarative_base
|
||||
from sqlalchemy.exc import OperationalError
|
||||
|
||||
|
||||
session = None
|
||||
from . import logger
|
||||
# session = None
|
||||
cc_exceptions = ['datetime', 'comments', 'composite', 'series']
|
||||
cc_classes = {}
|
||||
engine = None
|
||||
# engine = None
|
||||
|
||||
Base = declarative_base()
|
||||
|
||||
@ -226,6 +230,7 @@ class Publishers(Base):
|
||||
|
||||
class Data(Base):
|
||||
__tablename__ = 'data'
|
||||
__table_args__ = {'schema':'calibre'}
|
||||
|
||||
id = Column(Integer, primary_key=True)
|
||||
book = Column(Integer, ForeignKey('books.id'), nullable=False)
|
||||
@ -314,136 +319,170 @@ class Custom_Columns(Base):
|
||||
return display_dict
|
||||
|
||||
|
||||
def update_title_sort(config, conn=None):
|
||||
# user defined sort function for calibre databases (Series, etc.)
|
||||
def _title_sort(title):
|
||||
# calibre sort stuff
|
||||
title_pat = re.compile(config.config_title_regex, re.IGNORECASE)
|
||||
match = title_pat.search(title)
|
||||
if match:
|
||||
prep = match.group(1)
|
||||
title = title.replace(prep, '') + ', ' + prep
|
||||
return title.strip()
|
||||
class CalibreDB(threading.Thread):
|
||||
|
||||
conn = conn or session.connection().connection.connection
|
||||
conn.create_function("title_sort", 1, _title_sort)
|
||||
def __init__(self):
|
||||
threading.Thread.__init__(self)
|
||||
self.engine = None
|
||||
self.session = None
|
||||
self.queue = None
|
||||
self.log = None
|
||||
|
||||
def add_queue(self,queue):
|
||||
self.queue = queue
|
||||
self.log = logger.create()
|
||||
|
||||
def run(self):
|
||||
while True:
|
||||
i = self.queue.get()
|
||||
if i == 'dummy':
|
||||
self.queue.task_done()
|
||||
break
|
||||
if i['task'] == 'add_format':
|
||||
cur_book = self.session.query(Books).filter(Books.id == i['id']).first()
|
||||
cur_book.data.append(i['format'])
|
||||
try:
|
||||
# db.session.merge(cur_book)
|
||||
self.session.commit()
|
||||
except OperationalError as e:
|
||||
self.session.rollback()
|
||||
self.log.error("Database error: %s", e)
|
||||
# self._handleError(_(u"Database error: %(error)s.", error=e))
|
||||
# return
|
||||
self.queue.task_done()
|
||||
|
||||
|
||||
def setup_db(config, app_db_path):
|
||||
dispose()
|
||||
global engine
|
||||
def stop(self):
|
||||
self.queue.put('dummy')
|
||||
|
||||
if not config.config_calibre_dir:
|
||||
config.invalidate()
|
||||
return False
|
||||
def setup_db(self, config, app_db_path):
|
||||
self.dispose()
|
||||
# global engine
|
||||
|
||||
dbpath = os.path.join(config.config_calibre_dir, "metadata.db")
|
||||
if not os.path.exists(dbpath):
|
||||
config.invalidate()
|
||||
return False
|
||||
if not config.config_calibre_dir:
|
||||
config.invalidate()
|
||||
return False
|
||||
|
||||
try:
|
||||
#engine = create_engine('sqlite:///{0}'.format(dbpath),
|
||||
engine = create_engine('sqlite://',
|
||||
echo=False,
|
||||
isolation_level="SERIALIZABLE",
|
||||
connect_args={'check_same_thread': False})
|
||||
engine.execute("attach database '{}' as calibre;".format(dbpath))
|
||||
engine.execute("attach database '{}' as app_settings;".format(app_db_path))
|
||||
dbpath = os.path.join(config.config_calibre_dir, "metadata.db")
|
||||
if not os.path.exists(dbpath):
|
||||
config.invalidate()
|
||||
return False
|
||||
|
||||
conn = engine.connect()
|
||||
# conn.text_factory = lambda b: b.decode(errors = 'ignore') possible fix for #1302
|
||||
except Exception as e:
|
||||
config.invalidate(e)
|
||||
return False
|
||||
try:
|
||||
#engine = create_engine('sqlite:///{0}'.format(dbpath),
|
||||
self.engine = create_engine('sqlite://',
|
||||
echo=False,
|
||||
isolation_level="SERIALIZABLE",
|
||||
connect_args={'check_same_thread': False})
|
||||
self.engine.execute("attach database '{}' as calibre;".format(dbpath))
|
||||
self.engine.execute("attach database '{}' as app_settings;".format(app_db_path))
|
||||
|
||||
config.db_configured = True
|
||||
update_title_sort(config, conn.connection)
|
||||
conn = self.engine.connect()
|
||||
# conn.text_factory = lambda b: b.decode(errors = 'ignore') possible fix for #1302
|
||||
except Exception as e:
|
||||
config.invalidate(e)
|
||||
return False
|
||||
|
||||
if not cc_classes:
|
||||
cc = conn.execute("SELECT id, datatype FROM custom_columns")
|
||||
config.db_configured = True
|
||||
self.update_title_sort(config, conn.connection)
|
||||
|
||||
cc_ids = []
|
||||
books_custom_column_links = {}
|
||||
for row in cc:
|
||||
if row.datatype not in cc_exceptions:
|
||||
books_custom_column_links[row.id] = Table('books_custom_column_' + str(row.id) + '_link', Base.metadata,
|
||||
Column('book', Integer, ForeignKey('books.id'),
|
||||
primary_key=True),
|
||||
Column('value', Integer,
|
||||
ForeignKey('custom_column_' + str(row.id) + '.id'),
|
||||
primary_key=True)
|
||||
)
|
||||
cc_ids.append([row.id, row.datatype])
|
||||
if row.datatype == 'bool':
|
||||
ccdict = {'__tablename__': 'custom_column_' + str(row.id),
|
||||
'id': Column(Integer, primary_key=True),
|
||||
'book': Column(Integer, ForeignKey('books.id')),
|
||||
'value': Column(Boolean)}
|
||||
elif row.datatype == 'int':
|
||||
ccdict = {'__tablename__': 'custom_column_' + str(row.id),
|
||||
'id': Column(Integer, primary_key=True),
|
||||
'book': Column(Integer, ForeignKey('books.id')),
|
||||
'value': Column(Integer)}
|
||||
elif row.datatype == 'float':
|
||||
ccdict = {'__tablename__': 'custom_column_' + str(row.id),
|
||||
'id': Column(Integer, primary_key=True),
|
||||
'book': Column(Integer, ForeignKey('books.id')),
|
||||
'value': Column(Float)}
|
||||
if not cc_classes:
|
||||
cc = conn.execute("SELECT id, datatype FROM custom_columns")
|
||||
|
||||
cc_ids = []
|
||||
books_custom_column_links = {}
|
||||
for row in cc:
|
||||
if row.datatype not in cc_exceptions:
|
||||
books_custom_column_links[row.id] = Table('books_custom_column_' + str(row.id) + '_link', Base.metadata,
|
||||
Column('book', Integer, ForeignKey('books.id'),
|
||||
primary_key=True),
|
||||
Column('value', Integer,
|
||||
ForeignKey('custom_column_' + str(row.id) + '.id'),
|
||||
primary_key=True)
|
||||
)
|
||||
cc_ids.append([row.id, row.datatype])
|
||||
if row.datatype == 'bool':
|
||||
ccdict = {'__tablename__': 'custom_column_' + str(row.id),
|
||||
'id': Column(Integer, primary_key=True),
|
||||
'book': Column(Integer, ForeignKey('books.id')),
|
||||
'value': Column(Boolean)}
|
||||
elif row.datatype == 'int':
|
||||
ccdict = {'__tablename__': 'custom_column_' + str(row.id),
|
||||
'id': Column(Integer, primary_key=True),
|
||||
'book': Column(Integer, ForeignKey('books.id')),
|
||||
'value': Column(Integer)}
|
||||
elif row.datatype == 'float':
|
||||
ccdict = {'__tablename__': 'custom_column_' + str(row.id),
|
||||
'id': Column(Integer, primary_key=True),
|
||||
'book': Column(Integer, ForeignKey('books.id')),
|
||||
'value': Column(Float)}
|
||||
else:
|
||||
ccdict = {'__tablename__': 'custom_column_' + str(row.id),
|
||||
'id': Column(Integer, primary_key=True),
|
||||
'value': Column(String)}
|
||||
cc_classes[row.id] = type(str('Custom_Column_' + str(row.id)), (Base,), ccdict)
|
||||
|
||||
for cc_id in cc_ids:
|
||||
if (cc_id[1] == 'bool') or (cc_id[1] == 'int') or (cc_id[1] == 'float'):
|
||||
setattr(Books, 'custom_column_' + str(cc_id[0]), relationship(cc_classes[cc_id[0]],
|
||||
primaryjoin=(
|
||||
Books.id == cc_classes[cc_id[0]].book),
|
||||
backref='books'))
|
||||
else:
|
||||
ccdict = {'__tablename__': 'custom_column_' + str(row.id),
|
||||
'id': Column(Integer, primary_key=True),
|
||||
'value': Column(String)}
|
||||
cc_classes[row.id] = type(str('Custom_Column_' + str(row.id)), (Base,), ccdict)
|
||||
|
||||
for cc_id in cc_ids:
|
||||
if (cc_id[1] == 'bool') or (cc_id[1] == 'int') or (cc_id[1] == 'float'):
|
||||
setattr(Books, 'custom_column_' + str(cc_id[0]), relationship(cc_classes[cc_id[0]],
|
||||
primaryjoin=(
|
||||
Books.id == cc_classes[cc_id[0]].book),
|
||||
backref='books'))
|
||||
else:
|
||||
setattr(Books, 'custom_column_' + str(cc_id[0]), relationship(cc_classes[cc_id[0]],
|
||||
secondary=books_custom_column_links[cc_id[0]],
|
||||
backref='books'))
|
||||
setattr(Books, 'custom_column_' + str(cc_id[0]), relationship(cc_classes[cc_id[0]],
|
||||
secondary=books_custom_column_links[cc_id[0]],
|
||||
backref='books'))
|
||||
|
||||
|
||||
global session
|
||||
Session = scoped_session(sessionmaker(autocommit=False,
|
||||
autoflush=False,
|
||||
bind=engine))
|
||||
session = Session()
|
||||
return True
|
||||
# global session
|
||||
Session = scoped_session(sessionmaker(autocommit=False,
|
||||
autoflush=False,
|
||||
bind=self.engine))
|
||||
self.session = Session()
|
||||
return True
|
||||
|
||||
def update_title_sort(self, config, conn=None):
|
||||
# user defined sort function for calibre databases (Series, etc.)
|
||||
def _title_sort(title):
|
||||
# calibre sort stuff
|
||||
title_pat = re.compile(config.config_title_regex, re.IGNORECASE)
|
||||
match = title_pat.search(title)
|
||||
if match:
|
||||
prep = match.group(1)
|
||||
title = title.replace(prep, '') + ', ' + prep
|
||||
return title.strip()
|
||||
|
||||
conn = conn or self.session.connection().connection.connection
|
||||
conn.create_function("title_sort", 1, _title_sort)
|
||||
|
||||
def dispose(self):
|
||||
# global session
|
||||
|
||||
old_session = self.session
|
||||
self.session = None
|
||||
if old_session:
|
||||
try: old_session.close()
|
||||
except: pass
|
||||
if old_session.bind:
|
||||
try: old_session.bind.dispose()
|
||||
except Exception: pass
|
||||
|
||||
for attr in list(Books.__dict__.keys()):
|
||||
if attr.startswith("custom_column_"):
|
||||
setattr(Books, attr, None)
|
||||
|
||||
for db_class in cc_classes.values():
|
||||
Base.metadata.remove(db_class.__table__)
|
||||
cc_classes.clear()
|
||||
|
||||
for table in reversed(Base.metadata.sorted_tables):
|
||||
name = table.key
|
||||
if name.startswith("custom_column_") or name.startswith("books_custom_column_"):
|
||||
if table is not None:
|
||||
Base.metadata.remove(table)
|
||||
|
||||
|
||||
def dispose():
|
||||
global session
|
||||
|
||||
old_session = session
|
||||
session = None
|
||||
if old_session:
|
||||
try: old_session.close()
|
||||
except: pass
|
||||
if old_session.bind:
|
||||
try: old_session.bind.dispose()
|
||||
except Exception: pass
|
||||
|
||||
for attr in list(Books.__dict__.keys()):
|
||||
if attr.startswith("custom_column_"):
|
||||
setattr(Books, attr, None)
|
||||
|
||||
for db_class in cc_classes.values():
|
||||
Base.metadata.remove(db_class.__table__)
|
||||
cc_classes.clear()
|
||||
|
||||
for table in reversed(Base.metadata.sorted_tables):
|
||||
name = table.key
|
||||
if name.startswith("custom_column_") or name.startswith("books_custom_column_"):
|
||||
if table is not None:
|
||||
Base.metadata.remove(table)
|
||||
|
||||
|
||||
def reconnect_db(config, app_db_path):
|
||||
session.close()
|
||||
engine.dispose()
|
||||
setup_db(config, app_db_path)
|
||||
def reconnect_db(self, config, app_db_path):
|
||||
self.session.close()
|
||||
self.engine.dispose()
|
||||
self.setup_db(config, app_db_path)
|
||||
|
139
cps/editbooks.py
139
cps/editbooks.py
@ -33,7 +33,8 @@ from flask_login import current_user, login_required
|
||||
from sqlalchemy.exc import OperationalError
|
||||
|
||||
from . import constants, logger, isoLanguages, gdriveutils, uploader, helper
|
||||
from . import config, get_locale, db, ub, worker
|
||||
from . import config, get_locale, ub, worker, db
|
||||
from . import calibre_db
|
||||
from .helper import order_authors, common_filters
|
||||
from .web import login_required_if_no_ano, render_title_template, edit_required, upload_required
|
||||
|
||||
@ -175,7 +176,7 @@ def modify_identifiers(input_identifiers, db_identifiers, db_session):
|
||||
@login_required
|
||||
def delete_book(book_id, book_format):
|
||||
if current_user.role_delete_books():
|
||||
book = db.session.query(db.Books).filter(db.Books.id == book_id).first()
|
||||
book = calibre_db.session.query(db.Books).filter(db.Books.id == book_id).first()
|
||||
if book:
|
||||
try:
|
||||
result, error = helper.delete_book(book, config.config_calibre_dir, book_format=book_format.upper())
|
||||
@ -193,13 +194,13 @@ def delete_book(book_id, book_format):
|
||||
|
||||
# check if only this book links to:
|
||||
# author, language, series, tags, custom columns
|
||||
modify_database_object([u''], book.authors, db.Authors, db.session, 'author')
|
||||
modify_database_object([u''], book.tags, db.Tags, db.session, 'tags')
|
||||
modify_database_object([u''], book.series, db.Series, db.session, 'series')
|
||||
modify_database_object([u''], book.languages, db.Languages, db.session, 'languages')
|
||||
modify_database_object([u''], book.publishers, db.Publishers, db.session, 'publishers')
|
||||
modify_database_object([u''], book.authors, db.Authors, calibre_db.session, 'author')
|
||||
modify_database_object([u''], book.tags, db.Tags, calibre_db.session, 'tags')
|
||||
modify_database_object([u''], book.series, db.Series, calibre_db.session, 'series')
|
||||
modify_database_object([u''], book.languages, db.Languages, calibre_db.session, 'languages')
|
||||
modify_database_object([u''], book.publishers, db.Publishers, calibre_db.session, 'publishers')
|
||||
|
||||
cc = db.session.query(db.Custom_Columns).\
|
||||
cc = calibre_db.session.query(db.Custom_Columns).\
|
||||
filter(db.Custom_Columns.datatype.notin_(db.cc_exceptions)).all()
|
||||
for c in cc:
|
||||
cc_string = "custom_column_" + str(c.id)
|
||||
@ -209,32 +210,32 @@ def delete_book(book_id, book_format):
|
||||
del_cc = getattr(book, cc_string)[0]
|
||||
getattr(book, cc_string).remove(del_cc)
|
||||
log.debug('remove ' + str(c.id))
|
||||
db.session.delete(del_cc)
|
||||
db.session.commit()
|
||||
calibre_db.session.delete(del_cc)
|
||||
calibre_db.session.commit()
|
||||
elif c.datatype == 'rating':
|
||||
del_cc = getattr(book, cc_string)[0]
|
||||
getattr(book, cc_string).remove(del_cc)
|
||||
if len(del_cc.books) == 0:
|
||||
log.debug('remove ' + str(c.id))
|
||||
db.session.delete(del_cc)
|
||||
db.session.commit()
|
||||
calibre_db.session.delete(del_cc)
|
||||
calibre_db.session.commit()
|
||||
else:
|
||||
del_cc = getattr(book, cc_string)[0]
|
||||
getattr(book, cc_string).remove(del_cc)
|
||||
log.debug('remove ' + str(c.id))
|
||||
db.session.delete(del_cc)
|
||||
db.session.commit()
|
||||
calibre_db.session.delete(del_cc)
|
||||
calibre_db.session.commit()
|
||||
else:
|
||||
modify_database_object([u''], getattr(book, cc_string), db.cc_classes[c.id],
|
||||
db.session, 'custom')
|
||||
db.session.query(db.Books).filter(db.Books.id == book_id).delete()
|
||||
calibre_db.session, 'custom')
|
||||
calibre_db.session.query(db.Books).filter(db.Books.id == book_id).delete()
|
||||
else:
|
||||
db.session.query(db.Data).filter(db.Data.book == book.id).\
|
||||
calibre_db.session.query(db.Data).filter(db.Data.book == book.id).\
|
||||
filter(db.Data.format == book_format).delete()
|
||||
db.session.commit()
|
||||
calibre_db.session.commit()
|
||||
except Exception as e:
|
||||
log.debug(e)
|
||||
db.session.rollback()
|
||||
calibre_db.session.rollback()
|
||||
else:
|
||||
# book not found
|
||||
log.error('Book with id "%s" could not be deleted: not found', book_id)
|
||||
@ -247,9 +248,9 @@ def delete_book(book_id, book_format):
|
||||
|
||||
|
||||
def render_edit_book(book_id):
|
||||
db.update_title_sort(config)
|
||||
cc = db.session.query(db.Custom_Columns).filter(db.Custom_Columns.datatype.notin_(db.cc_exceptions)).all()
|
||||
book = db.session.query(db.Books)\
|
||||
calibre_db.update_title_sort(config)
|
||||
cc = calibre_db.session.query(db.Custom_Columns).filter(db.Custom_Columns.datatype.notin_(db.cc_exceptions)).all()
|
||||
book = calibre_db.session.query(db.Books)\
|
||||
.filter(db.Books.id == book_id).filter(common_filters()).first()
|
||||
|
||||
if not book:
|
||||
@ -304,7 +305,7 @@ def edit_book_ratings(to_save, book):
|
||||
ratingx2 = int(float(to_save["rating"]) * 2)
|
||||
if ratingx2 != old_rating:
|
||||
changed = True
|
||||
is_rating = db.session.query(db.Ratings).filter(db.Ratings.rating == ratingx2).first()
|
||||
is_rating = calibre_db.session.query(db.Ratings).filter(db.Ratings.rating == ratingx2).first()
|
||||
if is_rating:
|
||||
book.ratings.append(is_rating)
|
||||
else:
|
||||
@ -326,7 +327,7 @@ def edit_book_languages(to_save, book):
|
||||
for l in unknown_languages:
|
||||
log.error('%s is not a valid language', l)
|
||||
flash(_(u"%(langname)s is not a valid language", langname=l), category="error")
|
||||
return modify_database_object(list(input_l), book.languages, db.Languages, db.session, 'languages')
|
||||
return modify_database_object(list(input_l), book.languages, db.Languages, calibre_db.session, 'languages')
|
||||
|
||||
|
||||
def edit_book_publisher(to_save, book):
|
||||
@ -334,15 +335,15 @@ def edit_book_publisher(to_save, book):
|
||||
if to_save["publisher"]:
|
||||
publisher = to_save["publisher"].rstrip().strip()
|
||||
if len(book.publishers) == 0 or (len(book.publishers) > 0 and publisher != book.publishers[0].name):
|
||||
changed |= modify_database_object([publisher], book.publishers, db.Publishers, db.session, 'publisher')
|
||||
changed |= modify_database_object([publisher], book.publishers, db.Publishers, calibre_db.session, 'publisher')
|
||||
elif len(book.publishers):
|
||||
changed |= modify_database_object([], book.publishers, db.Publishers, db.session, 'publisher')
|
||||
changed |= modify_database_object([], book.publishers, db.Publishers, calibre_db.session, 'publisher')
|
||||
return changed
|
||||
|
||||
|
||||
def edit_cc_data(book_id, book, to_save):
|
||||
changed = False
|
||||
cc = db.session.query(db.Custom_Columns).filter(db.Custom_Columns.datatype.notin_(db.cc_exceptions)).all()
|
||||
cc = calibre_db.session.query(db.Custom_Columns).filter(db.Custom_Columns.datatype.notin_(db.cc_exceptions)).all()
|
||||
for c in cc:
|
||||
cc_string = "custom_column_" + str(c.id)
|
||||
if not c.is_multiple:
|
||||
@ -365,12 +366,12 @@ def edit_cc_data(book_id, book, to_save):
|
||||
else:
|
||||
del_cc = getattr(book, cc_string)[0]
|
||||
getattr(book, cc_string).remove(del_cc)
|
||||
db.session.delete(del_cc)
|
||||
calibre_db.session.delete(del_cc)
|
||||
changed = True
|
||||
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)
|
||||
calibre_db.session.add(new_cc)
|
||||
changed = True
|
||||
|
||||
else:
|
||||
@ -382,18 +383,18 @@ def edit_cc_data(book_id, book, to_save):
|
||||
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)
|
||||
calibre_db.session.delete(del_cc)
|
||||
changed = True
|
||||
cc_class = db.cc_classes[c.id]
|
||||
new_cc = db.session.query(cc_class).filter(
|
||||
new_cc = calibre_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)
|
||||
calibre_db.session.add(new_cc)
|
||||
changed = True
|
||||
db.session.flush()
|
||||
new_cc = db.session.query(cc_class).filter(
|
||||
calibre_db.session.flush()
|
||||
new_cc = calibre_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)
|
||||
@ -403,12 +404,12 @@ def edit_cc_data(book_id, book, to_save):
|
||||
del_cc = getattr(book, cc_string)[0]
|
||||
getattr(book, cc_string).remove(del_cc)
|
||||
if not del_cc.books or len(del_cc.books) == 0:
|
||||
db.session.delete(del_cc)
|
||||
calibre_db.session.delete(del_cc)
|
||||
changed = True
|
||||
else:
|
||||
input_tags = to_save[cc_string].split(',')
|
||||
input_tags = list(map(lambda it: it.strip(), input_tags))
|
||||
changed |= modify_database_object(input_tags, getattr(book, cc_string), db.cc_classes[c.id], db.session,
|
||||
changed |= modify_database_object(input_tags, getattr(book, cc_string), db.cc_classes[c.id], calibre_db.session,
|
||||
'custom')
|
||||
return changed
|
||||
|
||||
@ -446,7 +447,7 @@ def upload_single_file(request, book, book_id):
|
||||
return redirect(url_for('web.show_book', book_id=book.id))
|
||||
|
||||
file_size = os.path.getsize(saved_filename)
|
||||
is_format = db.session.query(db.Data).filter(db.Data.book == book_id).\
|
||||
is_format = calibre_db.session.query(db.Data).filter(db.Data.book == book_id).\
|
||||
filter(db.Data.format == file_ext.upper()).first()
|
||||
|
||||
# Format entry already exists, no need to update the database
|
||||
@ -455,11 +456,11 @@ def upload_single_file(request, book, book_id):
|
||||
else:
|
||||
try:
|
||||
db_format = db.Data(book_id, file_ext.upper(), file_size, file_name)
|
||||
db.session.add(db_format)
|
||||
db.session.commit()
|
||||
db.update_title_sort(config)
|
||||
calibre_db.session.add(db_format)
|
||||
calibre_db.session.commit()
|
||||
calibre_db.update_title_sort(config)
|
||||
except OperationalError as e:
|
||||
db.session.rollback()
|
||||
calibre_db.session.rollback()
|
||||
log.error('Database error: %s', e)
|
||||
flash(_(u"Database error: %(error)s.", error=e), category="error")
|
||||
return redirect(url_for('web.show_book', book_id=book.id))
|
||||
@ -498,8 +499,8 @@ def edit_book(book_id):
|
||||
return render_edit_book(book_id)
|
||||
|
||||
# create the function for sorting...
|
||||
db.update_title_sort(config)
|
||||
book = db.session.query(db.Books)\
|
||||
calibre_db.update_title_sort(config)
|
||||
book = calibre_db.session.query(db.Books)\
|
||||
.filter(db.Books.id == book_id).filter(common_filters()).first()
|
||||
|
||||
# Book not found
|
||||
@ -531,13 +532,13 @@ def edit_book(book_id):
|
||||
if input_authors == ['']:
|
||||
input_authors = [_(u'Unknown')] # prevent empty Author
|
||||
|
||||
modif_date |= modify_database_object(input_authors, book.authors, db.Authors, db.session, 'author')
|
||||
modif_date |= modify_database_object(input_authors, book.authors, db.Authors, calibre_db.session, 'author')
|
||||
|
||||
# Search for each author if author is in database, if not, authorname and sorted authorname is generated new
|
||||
# everything then is assembled for sorted author field in database
|
||||
sort_authors_list = list()
|
||||
for inp in input_authors:
|
||||
stored_author = db.session.query(db.Authors).filter(db.Authors.name == inp).first()
|
||||
stored_author = calibre_db.session.query(db.Authors).filter(db.Authors.name == inp).first()
|
||||
if not stored_author:
|
||||
stored_author = helper.get_sorted_author(inp)
|
||||
else:
|
||||
@ -581,17 +582,17 @@ def edit_book(book_id):
|
||||
|
||||
# Handle identifiers
|
||||
input_identifiers = identifier_list(to_save, book)
|
||||
modif_date |= modify_identifiers(input_identifiers, book.identifiers, db.session)
|
||||
modif_date |= modify_identifiers(input_identifiers, book.identifiers, calibre_db.session)
|
||||
|
||||
# Handle book tags
|
||||
input_tags = to_save["tags"].split(',')
|
||||
input_tags = list(map(lambda it: it.strip(), input_tags))
|
||||
modif_date |= modify_database_object(input_tags, book.tags, db.Tags, db.session, 'tags')
|
||||
modif_date |= modify_database_object(input_tags, book.tags, db.Tags, calibre_db.session, 'tags')
|
||||
|
||||
# Handle book series
|
||||
input_series = [to_save["series"].strip()]
|
||||
input_series = [x for x in input_series if x != '']
|
||||
modif_date |= modify_database_object(input_series, book.series, db.Series, db.session, 'series')
|
||||
modif_date |= modify_database_object(input_series, book.series, db.Series, calibre_db.session, 'series')
|
||||
|
||||
if to_save["pubdate"]:
|
||||
try:
|
||||
@ -615,7 +616,7 @@ def edit_book(book_id):
|
||||
|
||||
if modif_date:
|
||||
book.last_modified = datetime.utcnow()
|
||||
db.session.commit()
|
||||
calibre_db.session.commit()
|
||||
if config.config_use_google_drive:
|
||||
gdriveutils.updateGdriveCalibreFromLocal()
|
||||
if "detail_view" in to_save:
|
||||
@ -624,12 +625,12 @@ def edit_book(book_id):
|
||||
flash(_("Metadata successfully updated"), category="success")
|
||||
return render_edit_book(book_id)
|
||||
else:
|
||||
db.session.rollback()
|
||||
calibre_db.session.rollback()
|
||||
flash(error, category="error")
|
||||
return render_edit_book(book_id)
|
||||
except Exception as e:
|
||||
log.exception(e)
|
||||
db.session.rollback()
|
||||
calibre_db.session.rollback()
|
||||
flash(_("Error editing book, please check logfile for details"), category="error")
|
||||
return redirect(url_for('web.show_book', book_id=book.id))
|
||||
|
||||
@ -671,8 +672,8 @@ def upload():
|
||||
for requested_file in request.files.getlist("btn-upload"):
|
||||
try:
|
||||
# create the function for sorting...
|
||||
db.update_title_sort(config)
|
||||
db.session.connection().connection.connection.create_function('uuid4', 0, lambda: str(uuid4()))
|
||||
calibre_db.update_title_sort(config)
|
||||
calibre_db.session.connection().connection.connection.create_function('uuid4', 0, lambda: str(uuid4()))
|
||||
|
||||
# check if file extension is correct
|
||||
if '.' in requested_file.filename:
|
||||
@ -708,13 +709,13 @@ def upload():
|
||||
+ Markup(render_title_template('book_exists_flash.html', entry=entry)), category="warning")
|
||||
|
||||
# handle authors
|
||||
is_author = db.session.query(db.Authors).filter(db.Authors.name == authr).first()
|
||||
is_author = calibre_db.session.query(db.Authors).filter(db.Authors.name == authr).first()
|
||||
if is_author:
|
||||
db_author = is_author
|
||||
authr= is_author.name
|
||||
else:
|
||||
db_author = db.Authors(authr, helper.get_sorted_author(authr), "")
|
||||
db.session.add(db_author)
|
||||
calibre_db.session.add(db_author)
|
||||
|
||||
title_dir = helper.get_valid_filename(title)
|
||||
author_dir = helper.get_valid_filename(authr)
|
||||
@ -746,29 +747,29 @@ def upload():
|
||||
|
||||
# handle series
|
||||
db_series = None
|
||||
is_series = db.session.query(db.Series).filter(db.Series.name == series).first()
|
||||
is_series = calibre_db.session.query(db.Series).filter(db.Series.name == series).first()
|
||||
if is_series:
|
||||
db_series = is_series
|
||||
elif series != '':
|
||||
db_series = db.Series(series, "")
|
||||
db.session.add(db_series)
|
||||
calibre_db.session.add(db_series)
|
||||
|
||||
# add language actually one value in list
|
||||
input_language = meta.languages
|
||||
db_language = None
|
||||
if input_language != "":
|
||||
input_language = isoLanguages.get(name=input_language).part3
|
||||
hasLanguage = db.session.query(db.Languages).filter(db.Languages.lang_code == input_language).first()
|
||||
hasLanguage = calibre_db.session.query(db.Languages).filter(db.Languages.lang_code == input_language).first()
|
||||
if hasLanguage:
|
||||
db_language = hasLanguage
|
||||
else:
|
||||
db_language = db.Languages(input_language)
|
||||
db.session.add(db_language)
|
||||
calibre_db.session.add(db_language)
|
||||
|
||||
# If the language of the file is excluded from the users view, it's not imported, to allow the user to view
|
||||
# the book it's language is set to the filter language
|
||||
if db_language != current_user.filter_language() and current_user.filter_language() != "all":
|
||||
db_language = db.session.query(db.Languages).\
|
||||
db_language = calibre_db.session.query(db.Languages).\
|
||||
filter(db.Languages.lang_code == current_user.filter_language()).first()
|
||||
|
||||
# combine path and normalize path from windows systems
|
||||
@ -788,25 +789,25 @@ def upload():
|
||||
input_tags = tags.split(',')
|
||||
input_tags = list(map(lambda it: it.strip(), input_tags))
|
||||
if input_tags[0] !="":
|
||||
modify_database_object(input_tags, db_book.tags, db.Tags, db.session, 'tags')
|
||||
modify_database_object(input_tags, db_book.tags, db.Tags, calibre_db.session, 'tags')
|
||||
|
||||
# flush content, get db_book.id available
|
||||
db_book.data.append(db_data)
|
||||
db.session.add(db_book)
|
||||
db.session.flush()
|
||||
calibre_db.session.add(db_book)
|
||||
calibre_db.session.flush()
|
||||
|
||||
# add comment
|
||||
book_id = db_book.id
|
||||
upload_comment = Markup(meta.description).unescape()
|
||||
if upload_comment != "":
|
||||
db.session.add(db.Comments(upload_comment, book_id))
|
||||
calibre_db.session.add(db.Comments(upload_comment, book_id))
|
||||
|
||||
# save data to database, reread data
|
||||
db.session.commit()
|
||||
db.update_title_sort(config)
|
||||
calibre_db.session.commit()
|
||||
calibre_db.update_title_sort(config)
|
||||
# Reread book. It's important not to filter the result, as it could have language which hide it from
|
||||
# current users view (tags are not stored/extracted from metadata and could also be limited)
|
||||
book = db.session.query(db.Books).filter(db.Books.id == book_id).first()
|
||||
book = calibre_db.session.query(db.Books).filter(db.Books.id == book_id).first()
|
||||
# upload book to gdrive if nesseccary and add "(bookid)" to folder name
|
||||
if config.config_use_google_drive:
|
||||
gdriveutils.updateGdriveCalibreFromLocal()
|
||||
@ -823,7 +824,7 @@ def upload():
|
||||
flash(_(u"Failed to Move Cover File %(file)s: %(error)s", file=new_coverpath,
|
||||
error=e),
|
||||
category="error")
|
||||
db.session.commit()
|
||||
calibre_db.session.commit()
|
||||
if config.config_use_google_drive:
|
||||
gdriveutils.updateGdriveCalibreFromLocal()
|
||||
if error:
|
||||
@ -846,7 +847,7 @@ def upload():
|
||||
resp = {"location": url_for('web.show_book', book_id=db_book.id)}
|
||||
return Response(json.dumps(resp), mimetype='application/json')
|
||||
except OperationalError as e:
|
||||
db.session.rollback()
|
||||
calibre_db.session.rollback()
|
||||
log.error("Database error: %s", e)
|
||||
flash(_(u"Database error: %(error)s.", error=e), category="error")
|
||||
return Response(json.dumps({"location": url_for("web.index")}), mimetype='application/json')
|
||||
|
@ -23,7 +23,6 @@ import os
|
||||
import io
|
||||
import json
|
||||
import mimetypes
|
||||
import random
|
||||
import re
|
||||
import shutil
|
||||
import time
|
||||
@ -42,6 +41,7 @@ from flask_login import current_user
|
||||
from sqlalchemy.sql.expression import true, false, and_, or_, text, func
|
||||
from werkzeug.datastructures import Headers
|
||||
from werkzeug.security import generate_password_hash
|
||||
from . import calibre_db
|
||||
|
||||
try:
|
||||
from urllib.parse import quote
|
||||
@ -74,8 +74,8 @@ log = logger.create()
|
||||
|
||||
# Convert existing book entry to new format
|
||||
def convert_book_format(book_id, calibrepath, old_book_format, new_book_format, user_id, kindle_mail=None):
|
||||
book = db.session.query(db.Books).filter(db.Books.id == book_id).first()
|
||||
data = db.session.query(db.Data).filter(db.Data.book == book.id).filter(db.Data.format == old_book_format).first()
|
||||
book = calibre_db.session.query(db.Books).filter(db.Books.id == book_id).first()
|
||||
data = calibre_db.session.query(db.Data).filter(db.Data.book == book.id).filter(db.Data.format == old_book_format).first()
|
||||
if not data:
|
||||
error_message = _(u"%(format)s format not found for book id: %(book)d", format=old_book_format, book=book_id)
|
||||
log.error("convert_book_format: %s", error_message)
|
||||
@ -212,7 +212,7 @@ def check_read_formats(entry):
|
||||
# 3: If Pdf file is existing, it's directly send to kindle email
|
||||
def send_mail(book_id, book_format, convert, kindle_mail, calibrepath, user_id):
|
||||
"""Send email with attachments"""
|
||||
book = db.session.query(db.Books).filter(db.Books.id == book_id).first()
|
||||
book = calibre_db.session.query(db.Books).filter(db.Books.id == book_id).first()
|
||||
|
||||
if convert == 1:
|
||||
# returns None if success, otherwise errormessage
|
||||
@ -324,7 +324,7 @@ def delete_book_file(book, calibrepath, book_format=None):
|
||||
|
||||
|
||||
def update_dir_structure_file(book_id, calibrepath, first_author):
|
||||
localbook = db.session.query(db.Books).filter(db.Books.id == book_id).first()
|
||||
localbook = calibre_db.session.query(db.Books).filter(db.Books.id == book_id).first()
|
||||
path = os.path.join(calibrepath, localbook.path)
|
||||
|
||||
authordir = localbook.path.split('/')[0]
|
||||
@ -383,7 +383,7 @@ def update_dir_structure_file(book_id, calibrepath, first_author):
|
||||
|
||||
def update_dir_structure_gdrive(book_id, first_author):
|
||||
error = False
|
||||
book = db.session.query(db.Books).filter(db.Books.id == book_id).first()
|
||||
book = calibre_db.session.query(db.Books).filter(db.Books.id == book_id).first()
|
||||
path = book.path
|
||||
|
||||
authordir = book.path.split('/')[0]
|
||||
@ -494,13 +494,13 @@ def get_cover_on_failure(use_generic_cover):
|
||||
|
||||
|
||||
def get_book_cover(book_id):
|
||||
book = db.session.query(db.Books).filter(db.Books.id == book_id).filter(common_filters(allow_show_archived=True)).first()
|
||||
book = calibre_db.session.query(db.Books).filter(db.Books.id == book_id).filter(common_filters(allow_show_archived=True)).first()
|
||||
return get_book_cover_internal(book, use_generic_cover_on_failure=True)
|
||||
|
||||
|
||||
def get_book_cover_with_uuid(book_uuid,
|
||||
use_generic_cover_on_failure=True):
|
||||
book = db.session.query(db.Books).filter(db.Books.uuid == book_uuid).first()
|
||||
book = calibre_db.session.query(db.Books).filter(db.Books.uuid == book_uuid).first()
|
||||
return get_book_cover_internal(book, use_generic_cover_on_failure)
|
||||
|
||||
|
||||
@ -775,7 +775,7 @@ def tags_filters():
|
||||
# Creates for all stored languages a translated speaking name in the array for the UI
|
||||
def speaking_language(languages=None):
|
||||
if not languages:
|
||||
languages = db.session.query(db.Languages).join(db.books_languages_link).join(db.Books)\
|
||||
languages = calibre_db.session.query(db.Languages).join(db.books_languages_link).join(db.Books)\
|
||||
.filter(common_filters())\
|
||||
.group_by(text('books_languages_link.lang_code')).all()
|
||||
for lang in languages:
|
||||
@ -808,7 +808,7 @@ def order_authors(entry):
|
||||
error = False
|
||||
for auth in sort_authors:
|
||||
# ToDo: How to handle not found authorname
|
||||
result = db.session.query(db.Authors).filter(db.Authors.sort == auth.lstrip().strip()).first()
|
||||
result = calibre_db.session.query(db.Authors).filter(db.Authors.sort == auth.lstrip().strip()).first()
|
||||
if not result:
|
||||
error = True
|
||||
break
|
||||
@ -825,12 +825,12 @@ def fill_indexpage(page, database, db_filter, order, *join):
|
||||
|
||||
def fill_indexpage_with_archived_books(page, database, db_filter, order, allow_show_archived, *join):
|
||||
if current_user.show_detail_random():
|
||||
randm = db.session.query(db.Books).filter(common_filters(allow_show_archived))\
|
||||
randm = calibre_db.session.query(db.Books).filter(common_filters(allow_show_archived))\
|
||||
.order_by(func.random()).limit(config.config_random_books)
|
||||
else:
|
||||
randm = false()
|
||||
off = int(int(config.config_books_per_page) * (page - 1))
|
||||
query = db.session.query(database).join(*join, isouter=True).\
|
||||
query = calibre_db.session.query(database).join(*join, isouter=True).\
|
||||
filter(db_filter).\
|
||||
filter(common_filters(allow_show_archived))
|
||||
pagination = Pagination(page, config.config_books_per_page,
|
||||
@ -843,8 +843,8 @@ def fill_indexpage_with_archived_books(page, database, db_filter, order, allow_s
|
||||
|
||||
def get_typeahead(database, query, replace=('', ''), tag_filter=true()):
|
||||
query = query or ''
|
||||
db.session.connection().connection.connection.create_function("lower", 1, lcase)
|
||||
entries = db.session.query(database).filter(tag_filter).\
|
||||
calibre_db.session.connection().connection.connection.create_function("lower", 1, lcase)
|
||||
entries = calibre_db.session.query(database).filter(tag_filter).\
|
||||
filter(func.lower(database.name).ilike("%" + query + "%")).all()
|
||||
json_dumps = json.dumps([dict(name=r.name.replace(*replace)) for r in entries])
|
||||
return json_dumps
|
||||
@ -852,7 +852,7 @@ def get_typeahead(database, query, replace=('', ''), tag_filter=true()):
|
||||
|
||||
# read search results from calibre-database and return it (function is used for feed and simple search
|
||||
def get_search_results(term):
|
||||
db.session.connection().connection.connection.create_function("lower", 1, lcase)
|
||||
calibre_db.session.connection().connection.connection.create_function("lower", 1, lcase)
|
||||
q = list()
|
||||
authorterms = re.split("[, ]+", term)
|
||||
for authorterm in authorterms:
|
||||
@ -860,7 +860,7 @@ def get_search_results(term):
|
||||
|
||||
db.Books.authors.any(func.lower(db.Authors.name).ilike("%" + term + "%"))
|
||||
|
||||
return db.session.query(db.Books).filter(common_filters()).filter(
|
||||
return calibre_db.session.query(db.Books).filter(common_filters()).filter(
|
||||
or_(db.Books.tags.any(func.lower(db.Tags.name).ilike("%" + term + "%")),
|
||||
db.Books.series.any(func.lower(db.Series.name).ilike("%" + term + "%")),
|
||||
db.Books.authors.any(and_(*q)),
|
||||
@ -870,7 +870,7 @@ def get_search_results(term):
|
||||
|
||||
|
||||
def get_cc_columns(filter_config_custom_read=False):
|
||||
tmpcc = db.session.query(db.Custom_Columns).filter(db.Custom_Columns.datatype.notin_(db.cc_exceptions)).all()
|
||||
tmpcc = calibre_db.session.query(db.Custom_Columns).filter(db.Custom_Columns.datatype.notin_(db.cc_exceptions)).all()
|
||||
cc = []
|
||||
r = None
|
||||
if config.config_columns_to_ignore:
|
||||
@ -887,9 +887,9 @@ def get_cc_columns(filter_config_custom_read=False):
|
||||
|
||||
def get_download_link(book_id, book_format, client):
|
||||
book_format = book_format.split(".")[0]
|
||||
book = db.session.query(db.Books).filter(db.Books.id == book_id).filter(common_filters()).first()
|
||||
book = calibre_db.session.query(db.Books).filter(db.Books.id == book_id).filter(common_filters()).first()
|
||||
if book:
|
||||
data1 = db.session.query(db.Data).filter(db.Data.book == book.id)\
|
||||
data1 = calibre_db.session.query(db.Data).filter(db.Data.book == book.id)\
|
||||
.filter(db.Data.format == book_format.upper()).first()
|
||||
else:
|
||||
abort(404)
|
||||
@ -911,13 +911,13 @@ def get_download_link(book_id, book_format, client):
|
||||
|
||||
|
||||
def check_exists_book(authr, title):
|
||||
db.session.connection().connection.connection.create_function("lower", 1, lcase)
|
||||
calibre_db.session.connection().connection.connection.create_function("lower", 1, lcase)
|
||||
q = list()
|
||||
authorterms = re.split(r'\s*&\s*', authr)
|
||||
for authorterm in authorterms:
|
||||
q.append(db.Books.authors.any(func.lower(db.Authors.name).ilike("%" + authorterm + "%")))
|
||||
|
||||
return db.session.query(db.Books).filter(
|
||||
return calibre_db.session.query(db.Books).filter(
|
||||
and_(db.Books.authors.any(and_(*q)),
|
||||
func.lower(db.Books.title).ilike("%" + title + "%")
|
||||
)).first()
|
||||
|
18
cps/kobo.py
18
cps/kobo.py
@ -48,7 +48,7 @@ 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
|
||||
from . import config, logger, kobo_auth, db, calibre_db, helper, shelf as shelf_lib, ub
|
||||
from .services import SyncToken as SyncToken
|
||||
from .web import download_required
|
||||
from .kobo_auth import requires_kobo_auth
|
||||
@ -170,7 +170,7 @@ def HandleSyncRequest():
|
||||
# It looks like it's treating the db.Books.last_modified field as a string and may fail
|
||||
# the comparison because of the +00:00 suffix.
|
||||
changed_entries = (
|
||||
db.session.query(db.Books)
|
||||
calibre_db.session.query(db.Books)
|
||||
.join(db.Data)
|
||||
.filter(or_(func.datetime(db.Books.last_modified) > sync_token.books_last_modified,
|
||||
db.Books.id.in_(recently_restored_or_archived_books)))
|
||||
@ -207,7 +207,7 @@ def HandleSyncRequest():
|
||||
ub.KoboReadingState.user_id == current_user.id,
|
||||
ub.KoboReadingState.book_id.notin_(reading_states_in_new_entitlements))))
|
||||
for kobo_reading_state in changed_reading_states.all():
|
||||
book = db.session.query(db.Books).filter(db.Books.id == kobo_reading_state.book_id).one_or_none()
|
||||
book = calibre_db.session.query(db.Books).filter(db.Books.id == kobo_reading_state.book_id).one_or_none()
|
||||
if book:
|
||||
sync_results.append({
|
||||
"ChangedReadingState": {
|
||||
@ -256,7 +256,7 @@ def HandleMetadataRequest(book_uuid):
|
||||
if not current_app.wsgi_app.is_proxied:
|
||||
log.debug('Kobo: Received unproxied request, changed request port to server port')
|
||||
log.info("Kobo library metadata request received for book %s" % book_uuid)
|
||||
book = db.session.query(db.Books).filter(db.Books.uuid == book_uuid).first()
|
||||
book = calibre_db.session.query(db.Books).filter(db.Books.uuid == book_uuid).first()
|
||||
if not book or not book.data:
|
||||
log.info(u"Book %s not found in database", book_uuid)
|
||||
return redirect_or_proxy_request()
|
||||
@ -474,7 +474,7 @@ def add_items_to_shelf(items, shelf):
|
||||
items_unknown_to_calibre.append(item)
|
||||
continue
|
||||
|
||||
book = db.session.query(db.Books).filter(db.Books.uuid == item["RevisionId"]).one_or_none()
|
||||
book = calibre_db.session.query(db.Books).filter(db.Books.uuid == item["RevisionId"]).one_or_none()
|
||||
if not book:
|
||||
items_unknown_to_calibre.append(item)
|
||||
continue
|
||||
@ -545,7 +545,7 @@ def HandleTagRemoveItem(tag_id):
|
||||
items_unknown_to_calibre.append(item)
|
||||
continue
|
||||
|
||||
book = db.session.query(db.Books).filter(db.Books.uuid == item["RevisionId"]).one_or_none()
|
||||
book = calibre_db.session.query(db.Books).filter(db.Books.uuid == item["RevisionId"]).one_or_none()
|
||||
if not book:
|
||||
items_unknown_to_calibre.append(item)
|
||||
continue
|
||||
@ -613,7 +613,7 @@ def create_kobo_tag(shelf):
|
||||
"Type": "UserTag"
|
||||
}
|
||||
for book_shelf in shelf.books:
|
||||
book = db.session.query(db.Books).filter(db.Books.id == book_shelf.book_id).one_or_none()
|
||||
book = calibre_db.session.query(db.Books).filter(db.Books.id == book_shelf.book_id).one_or_none()
|
||||
if not book:
|
||||
log.info(u"Book (id: %s) in BookShelf (id: %s) not found in book database", book_shelf.book_id, shelf.id)
|
||||
continue
|
||||
@ -629,7 +629,7 @@ def create_kobo_tag(shelf):
|
||||
@kobo.route("/v1/library/<book_uuid>/state", methods=["GET", "PUT"])
|
||||
@login_required
|
||||
def HandleStateRequest(book_uuid):
|
||||
book = db.session.query(db.Books).filter(db.Books.uuid == book_uuid).first()
|
||||
book = calibre_db.session.query(db.Books).filter(db.Books.uuid == book_uuid).first()
|
||||
if not book or not book.data:
|
||||
log.info(u"Book %s not found in database", book_uuid)
|
||||
return redirect_or_proxy_request()
|
||||
@ -804,7 +804,7 @@ def TopLevelEndpoint():
|
||||
@login_required
|
||||
def HandleBookDeletionRequest(book_uuid):
|
||||
log.info("Kobo book deletion request received for book %s" % book_uuid)
|
||||
book = db.session.query(db.Books).filter(db.Books.uuid == book_uuid).first()
|
||||
book = calibre_db.session.query(db.Books).filter(db.Books.uuid == book_uuid).first()
|
||||
if not book:
|
||||
log.info(u"Book %s not found in database", book_uuid)
|
||||
return redirect_or_proxy_request()
|
||||
|
34
cps/opds.py
34
cps/opds.py
@ -30,7 +30,7 @@ from flask_login import current_user
|
||||
from sqlalchemy.sql.expression import func, text, or_, and_
|
||||
from werkzeug.security import check_password_hash
|
||||
|
||||
from . import constants, logger, config, db, ub, services, get_locale, isoLanguages
|
||||
from . import constants, logger, config, db, calibre_db, ub, services, get_locale, isoLanguages
|
||||
from .helper import fill_indexpage, get_download_link, get_book_cover, speaking_language
|
||||
from .pagination import Pagination
|
||||
from .web import common_filters, get_search_results, render_read_books, download_required
|
||||
@ -108,7 +108,7 @@ def feed_new():
|
||||
@opds.route("/opds/discover")
|
||||
@requires_basic_auth_if_no_ano
|
||||
def feed_discover():
|
||||
entries = db.session.query(db.Books).filter(common_filters()).order_by(func.random())\
|
||||
entries = calibre_db.session.query(db.Books).filter(common_filters()).order_by(func.random())\
|
||||
.limit(config.config_books_per_page)
|
||||
pagination = Pagination(1, config.config_books_per_page, int(config.config_books_per_page))
|
||||
return render_xml_template('feed.xml', entries=entries, pagination=pagination)
|
||||
@ -133,10 +133,10 @@ def feed_hot():
|
||||
hot_books = all_books.offset(off).limit(config.config_books_per_page)
|
||||
entries = list()
|
||||
for book in hot_books:
|
||||
downloadBook = db.session.query(db.Books).filter(db.Books.id == book.Downloads.book_id).first()
|
||||
downloadBook = calibre_db.session.query(db.Books).filter(db.Books.id == book.Downloads.book_id).first()
|
||||
if downloadBook:
|
||||
entries.append(
|
||||
db.session.query(db.Books).filter(common_filters())
|
||||
calibre_db.session.query(db.Books).filter(common_filters())
|
||||
.filter(db.Books.id == book.Downloads.book_id).first()
|
||||
)
|
||||
else:
|
||||
@ -153,11 +153,11 @@ def feed_hot():
|
||||
@requires_basic_auth_if_no_ano
|
||||
def feed_authorindex():
|
||||
off = request.args.get("offset") or 0
|
||||
entries = db.session.query(db.Authors).join(db.books_authors_link).join(db.Books).filter(common_filters())\
|
||||
entries = calibre_db.session.query(db.Authors).join(db.books_authors_link).join(db.Books).filter(common_filters())\
|
||||
.group_by(text('books_authors_link.author')).order_by(db.Authors.sort).limit(config.config_books_per_page)\
|
||||
.offset(off)
|
||||
pagination = Pagination((int(off) / (int(config.config_books_per_page)) + 1), config.config_books_per_page,
|
||||
len(db.session.query(db.Authors).all()))
|
||||
len(calibre_db.session.query(db.Authors).all()))
|
||||
return render_xml_template('feed.xml', listelements=entries, folder='opds.feed_author', pagination=pagination)
|
||||
|
||||
|
||||
@ -176,11 +176,11 @@ def feed_author(book_id):
|
||||
@requires_basic_auth_if_no_ano
|
||||
def feed_publisherindex():
|
||||
off = request.args.get("offset") or 0
|
||||
entries = db.session.query(db.Publishers).join(db.books_publishers_link).join(db.Books).filter(common_filters())\
|
||||
entries = calibre_db.session.query(db.Publishers).join(db.books_publishers_link).join(db.Books).filter(common_filters())\
|
||||
.group_by(text('books_publishers_link.publisher')).order_by(db.Publishers.sort)\
|
||||
.limit(config.config_books_per_page).offset(off)
|
||||
pagination = Pagination((int(off) / (int(config.config_books_per_page)) + 1), config.config_books_per_page,
|
||||
len(db.session.query(db.Publishers).all()))
|
||||
len(calibre_db.session.query(db.Publishers).all()))
|
||||
return render_xml_template('feed.xml', listelements=entries, folder='opds.feed_publisher', pagination=pagination)
|
||||
|
||||
|
||||
@ -199,10 +199,10 @@ def feed_publisher(book_id):
|
||||
@requires_basic_auth_if_no_ano
|
||||
def feed_categoryindex():
|
||||
off = request.args.get("offset") or 0
|
||||
entries = db.session.query(db.Tags).join(db.books_tags_link).join(db.Books).filter(common_filters())\
|
||||
entries = calibre_db.session.query(db.Tags).join(db.books_tags_link).join(db.Books).filter(common_filters())\
|
||||
.group_by(text('books_tags_link.tag')).order_by(db.Tags.name).offset(off).limit(config.config_books_per_page)
|
||||
pagination = Pagination((int(off) / (int(config.config_books_per_page)) + 1), config.config_books_per_page,
|
||||
len(db.session.query(db.Tags).all()))
|
||||
len(calibre_db.session.query(db.Tags).all()))
|
||||
return render_xml_template('feed.xml', listelements=entries, folder='opds.feed_category', pagination=pagination)
|
||||
|
||||
|
||||
@ -221,10 +221,10 @@ def feed_category(book_id):
|
||||
@requires_basic_auth_if_no_ano
|
||||
def feed_seriesindex():
|
||||
off = request.args.get("offset") or 0
|
||||
entries = db.session.query(db.Series).join(db.books_series_link).join(db.Books).filter(common_filters())\
|
||||
entries = calibre_db.session.query(db.Series).join(db.books_series_link).join(db.Books).filter(common_filters())\
|
||||
.group_by(text('books_series_link.series')).order_by(db.Series.sort).offset(off).all()
|
||||
pagination = Pagination((int(off) / (int(config.config_books_per_page)) + 1), config.config_books_per_page,
|
||||
len(db.session.query(db.Series).all()))
|
||||
len(calibre_db.session.query(db.Series).all()))
|
||||
return render_xml_template('feed.xml', listelements=entries, folder='opds.feed_series', pagination=pagination)
|
||||
|
||||
|
||||
@ -243,7 +243,7 @@ def feed_series(book_id):
|
||||
@requires_basic_auth_if_no_ano
|
||||
def feed_ratingindex():
|
||||
off = request.args.get("offset") or 0
|
||||
entries = db.session.query(db.Ratings, func.count('books_ratings_link.book').label('count'),
|
||||
entries = calibre_db.session.query(db.Ratings, func.count('books_ratings_link.book').label('count'),
|
||||
(db.Ratings.rating / 2).label('name')) \
|
||||
.join(db.books_ratings_link).join(db.Books).filter(common_filters()) \
|
||||
.group_by(text('books_ratings_link.rating')).order_by(db.Ratings.rating).all()
|
||||
@ -271,7 +271,7 @@ def feed_ratings(book_id):
|
||||
@requires_basic_auth_if_no_ano
|
||||
def feed_formatindex():
|
||||
off = request.args.get("offset") or 0
|
||||
entries = db.session.query(db.Data).join(db.Books).filter(common_filters()) \
|
||||
entries = calibre_db.session.query(db.Data).join(db.Books).filter(common_filters()) \
|
||||
.group_by(db.Data.format).order_by(db.Data.format).all()
|
||||
pagination = Pagination((int(off) / (int(config.config_books_per_page)) + 1), config.config_books_per_page,
|
||||
len(entries))
|
||||
@ -305,7 +305,7 @@ def feed_languagesindex():
|
||||
cur_l = LC.parse(current_user.filter_language())
|
||||
except UnknownLocaleError:
|
||||
cur_l = None
|
||||
languages = db.session.query(db.Languages).filter(
|
||||
languages = calibre_db.session.query(db.Languages).filter(
|
||||
db.Languages.lang_code == current_user.filter_language()).all()
|
||||
if cur_l:
|
||||
languages[0].name = cur_l.get_language_name(get_locale())
|
||||
@ -356,7 +356,7 @@ def feed_shelf(book_id):
|
||||
books_in_shelf = ub.session.query(ub.BookShelf).filter(ub.BookShelf.shelf == book_id).order_by(
|
||||
ub.BookShelf.order.asc()).all()
|
||||
for book in books_in_shelf:
|
||||
cur_book = db.session.query(db.Books).filter(db.Books.id == book.book_id).first()
|
||||
cur_book = calibre_db.session.query(db.Books).filter(db.Books.id == book.book_id).first()
|
||||
result.append(cur_book)
|
||||
pagination = Pagination((int(off) / (int(config.config_books_per_page)) + 1), config.config_books_per_page,
|
||||
len(result))
|
||||
@ -378,7 +378,7 @@ def opds_download_link(book_id, book_format):
|
||||
@opds.route("/ajax/book/<string:uuid>", defaults={'library': ""})
|
||||
@requires_basic_auth_if_no_ano
|
||||
def get_metadata_calibre_companion(uuid, library):
|
||||
entry = db.session.query(db.Books).filter(db.Books.uuid.like("%" + uuid + "%")).first()
|
||||
entry = calibre_db.session.query(db.Books).filter(db.Books.uuid.like("%" + uuid + "%")).first()
|
||||
if entry is not None:
|
||||
js = render_template('json.txt', entry=entry)
|
||||
response = make_response(js)
|
||||
|
@ -196,6 +196,9 @@ class WebServer(object):
|
||||
def stop(self, restart=False):
|
||||
from . import updater_thread
|
||||
updater_thread.stop()
|
||||
from . import calibre_db
|
||||
calibre_db.stop()
|
||||
|
||||
|
||||
log.info("webserver stop (restart=%s)", restart)
|
||||
self.restart = restart
|
||||
|
10
cps/shelf.py
10
cps/shelf.py
@ -28,7 +28,7 @@ from flask_babel import gettext as _
|
||||
from flask_login import login_required, current_user
|
||||
from sqlalchemy.sql.expression import func
|
||||
|
||||
from . import logger, ub, searched_ids, db
|
||||
from . import logger, ub, searched_ids, db, calibre_db
|
||||
from .web import render_title_template
|
||||
from .helper import common_filters
|
||||
|
||||
@ -320,11 +320,11 @@ def show_shelf(shelf_type, shelf_id):
|
||||
books_in_shelf = ub.session.query(ub.BookShelf).filter(ub.BookShelf.shelf == shelf_id)\
|
||||
.order_by(ub.BookShelf.order.asc()).all()
|
||||
for book in books_in_shelf:
|
||||
cur_book = db.session.query(db.Books).filter(db.Books.id == book.book_id).filter(common_filters()).first()
|
||||
cur_book = calibre_db.session.query(db.Books).filter(db.Books.id == book.book_id).filter(common_filters()).first()
|
||||
if cur_book:
|
||||
result.append(cur_book)
|
||||
else:
|
||||
cur_book = db.session.query(db.Books).filter(db.Books.id == book.book_id).first()
|
||||
cur_book = calibre_db.session.query(db.Books).filter(db.Books.id == book.book_id).first()
|
||||
if not cur_book:
|
||||
log.info('Not existing book %s in %s deleted', book.book_id, shelf)
|
||||
ub.session.query(ub.BookShelf).filter(ub.BookShelf.book_id == book.book_id).delete()
|
||||
@ -356,7 +356,7 @@ def order_shelf(shelf_id):
|
||||
books_in_shelf2 = ub.session.query(ub.BookShelf).filter(ub.BookShelf.shelf == shelf_id) \
|
||||
.order_by(ub.BookShelf.order.asc()).all()
|
||||
for book in books_in_shelf2:
|
||||
cur_book = db.session.query(db.Books).filter(db.Books.id == book.book_id).filter(common_filters()).first()
|
||||
cur_book = calibre_db.session.query(db.Books).filter(db.Books.id == book.book_id).filter(common_filters()).first()
|
||||
if cur_book:
|
||||
result.append({'title': cur_book.title,
|
||||
'id': cur_book.id,
|
||||
@ -364,7 +364,7 @@ def order_shelf(shelf_id):
|
||||
'series': cur_book.series,
|
||||
'series_index': cur_book.series_index})
|
||||
else:
|
||||
cur_book = db.session.query(db.Books).filter(db.Books.id == book.book_id).first()
|
||||
cur_book = calibre_db.session.query(db.Books).filter(db.Books.id == book.book_id).first()
|
||||
result.append({'title': _('Hidden Book'),
|
||||
'id': cur_book.id,
|
||||
'author': [],
|
||||
|
95
cps/web.py
95
cps/web.py
@ -50,6 +50,7 @@ from werkzeug.security import generate_password_hash, check_password_hash
|
||||
|
||||
from . import constants, logger, isoLanguages, services, worker
|
||||
from . import searched_ids, lm, babel, db, ub, config, get_locale, app
|
||||
from . import calibre_db
|
||||
from .gdriveutils import getFileFromEbooksFolder, do_gdrive_download
|
||||
from .helper import common_filters, get_search_results, fill_indexpage, fill_indexpage_with_archived_books, \
|
||||
speaking_language, check_valid_domain, order_authors, get_typeahead, render_task_status, json_serial, \
|
||||
@ -438,21 +439,21 @@ def toggle_read(book_id):
|
||||
ub.session.commit()
|
||||
else:
|
||||
try:
|
||||
db.update_title_sort(config)
|
||||
book = db.session.query(db.Books).filter(db.Books.id == book_id).filter(common_filters()).first()
|
||||
calibre_db.update_title_sort(config)
|
||||
book = calibre_db.session.query(db.Books).filter(db.Books.id == book_id).filter(common_filters()).first()
|
||||
read_status = getattr(book, 'custom_column_' + str(config.config_read_column))
|
||||
if len(read_status):
|
||||
read_status[0].value = not read_status[0].value
|
||||
db.session.commit()
|
||||
calibre_db.session.commit()
|
||||
else:
|
||||
cc_class = db.cc_classes[config.config_read_column]
|
||||
new_cc = cc_class(value=1, book=book_id)
|
||||
db.session.add(new_cc)
|
||||
db.session.commit()
|
||||
calibre_db.session.add(new_cc)
|
||||
calibre_db.session.commit()
|
||||
except KeyError:
|
||||
log.error(u"Custom Column No.%d is not exisiting in calibre database", config.config_read_column)
|
||||
except OperationalError as e:
|
||||
db.session.rollback()
|
||||
calibre_db.session.rollback()
|
||||
log.error(u"Read status could not set: %e", e)
|
||||
|
||||
return ""
|
||||
@ -496,7 +497,7 @@ def update_view():
|
||||
@web.route("/ajax/getcomic/<int:book_id>/<book_format>/<int:page>")
|
||||
@login_required
|
||||
def get_comic_book(book_id, book_format, page):
|
||||
book = db.session.query(db.Books).filter(db.Books.id == book_id).first()
|
||||
book = calibre_db.session.query(db.Books).filter(db.Books.id == book_id).first()
|
||||
if not book:
|
||||
return "", 204
|
||||
else:
|
||||
@ -589,8 +590,8 @@ def get_languages_json():
|
||||
@login_required_if_no_ano
|
||||
def get_matching_tags():
|
||||
tag_dict = {'tags': []}
|
||||
q = db.session.query(db.Books)
|
||||
db.session.connection().connection.connection.create_function("lower", 1, lcase)
|
||||
q = calibre_db.session.query(db.Books)
|
||||
calibre_db.session.connection().connection.connection.create_function("lower", 1, lcase)
|
||||
author_input = request.args.get('author_name') or ''
|
||||
title_input = request.args.get('book_title') or ''
|
||||
include_tag_inputs = request.args.getlist('include_tag') or ''
|
||||
@ -692,7 +693,7 @@ def books_list(data, sort, book_id, page):
|
||||
def render_hot_books(page):
|
||||
if current_user.check_visibility(constants.SIDEBAR_HOT):
|
||||
if current_user.show_detail_random():
|
||||
random = db.session.query(db.Books).filter(common_filters()) \
|
||||
random = calibre_db.session.query(db.Books).filter(common_filters()) \
|
||||
.order_by(func.random()).limit(config.config_random_books)
|
||||
else:
|
||||
random = false()
|
||||
@ -702,7 +703,7 @@ def render_hot_books(page):
|
||||
hot_books = all_books.offset(off).limit(config.config_books_per_page)
|
||||
entries = list()
|
||||
for book in hot_books:
|
||||
downloadBook = db.session.query(db.Books).filter(common_filters()).filter(
|
||||
downloadBook = calibre_db.session.query(db.Books).filter(common_filters()).filter(
|
||||
db.Books.id == book.Downloads.book_id).first()
|
||||
if downloadBook:
|
||||
entries.append(downloadBook)
|
||||
@ -727,7 +728,7 @@ def render_author_books(page, author_id, order):
|
||||
category="error")
|
||||
return redirect(url_for("web.index"))
|
||||
|
||||
author = db.session.query(db.Authors).get(author_id)
|
||||
author = calibre_db.session.query(db.Authors).get(author_id)
|
||||
author_name = author.name.replace('|', ',')
|
||||
|
||||
author_info = None
|
||||
@ -742,7 +743,7 @@ def render_author_books(page, author_id, order):
|
||||
|
||||
|
||||
def render_publisher_books(page, book_id, order):
|
||||
publisher = db.session.query(db.Publishers).filter(db.Publishers.id == book_id).first()
|
||||
publisher = calibre_db.session.query(db.Publishers).filter(db.Publishers.id == book_id).first()
|
||||
if publisher:
|
||||
entries, random, pagination = fill_indexpage(page, db.Books,
|
||||
db.Books.publishers.any(db.Publishers.id == book_id),
|
||||
@ -755,7 +756,7 @@ def render_publisher_books(page, book_id, order):
|
||||
|
||||
|
||||
def render_series_books(page, book_id, order):
|
||||
name = db.session.query(db.Series).filter(db.Series.id == book_id).first()
|
||||
name = calibre_db.session.query(db.Series).filter(db.Series.id == book_id).first()
|
||||
if name:
|
||||
entries, random, pagination = fill_indexpage(page, db.Books, db.Books.series.any(db.Series.id == book_id),
|
||||
[db.Books.series_index, order[0]])
|
||||
@ -766,7 +767,7 @@ def render_series_books(page, book_id, order):
|
||||
|
||||
|
||||
def render_ratings_books(page, book_id, order):
|
||||
name = db.session.query(db.Ratings).filter(db.Ratings.id == book_id).first()
|
||||
name = calibre_db.session.query(db.Ratings).filter(db.Ratings.id == book_id).first()
|
||||
entries, random, pagination = fill_indexpage(page, db.Books, db.Books.ratings.any(db.Ratings.id == book_id),
|
||||
[db.Books.timestamp.desc(), order[0]])
|
||||
if name and name.rating <= 10:
|
||||
@ -777,7 +778,7 @@ def render_ratings_books(page, book_id, order):
|
||||
|
||||
|
||||
def render_formats_books(page, book_id, order):
|
||||
name = db.session.query(db.Data).filter(db.Data.format == book_id.upper()).first()
|
||||
name = calibre_db.session.query(db.Data).filter(db.Data.format == book_id.upper()).first()
|
||||
if name:
|
||||
entries, random, pagination = fill_indexpage(page, db.Books,
|
||||
db.Books.data.any(db.Data.format == book_id.upper()),
|
||||
@ -789,7 +790,7 @@ def render_formats_books(page, book_id, order):
|
||||
|
||||
|
||||
def render_category_books(page, book_id, order):
|
||||
name = db.session.query(db.Tags).filter(db.Tags.id == book_id).first()
|
||||
name = calibre_db.session.query(db.Tags).filter(db.Tags.id == book_id).first()
|
||||
if name:
|
||||
entries, random, pagination = fill_indexpage(page, db.Books, db.Books.tags.any(db.Tags.id == book_id),
|
||||
[order[0], db.Series.name, db.Books.series_index],
|
||||
@ -825,10 +826,10 @@ def books_table():
|
||||
@login_required_if_no_ano
|
||||
def author_list():
|
||||
if current_user.check_visibility(constants.SIDEBAR_AUTHOR):
|
||||
entries = db.session.query(db.Authors, func.count('books_authors_link.book').label('count')) \
|
||||
entries = calibre_db.session.query(db.Authors, func.count('books_authors_link.book').label('count')) \
|
||||
.join(db.books_authors_link).join(db.Books).filter(common_filters()) \
|
||||
.group_by(text('books_authors_link.author')).order_by(db.Authors.sort).all()
|
||||
charlist = db.session.query(func.upper(func.substr(db.Authors.sort, 1, 1)).label('char')) \
|
||||
charlist = calibre_db.session.query(func.upper(func.substr(db.Authors.sort, 1, 1)).label('char')) \
|
||||
.join(db.books_authors_link).join(db.Books).filter(common_filters()) \
|
||||
.group_by(func.upper(func.substr(db.Authors.sort, 1, 1))).all()
|
||||
for entry in entries:
|
||||
@ -843,10 +844,10 @@ def author_list():
|
||||
@login_required_if_no_ano
|
||||
def publisher_list():
|
||||
if current_user.check_visibility(constants.SIDEBAR_PUBLISHER):
|
||||
entries = db.session.query(db.Publishers, func.count('books_publishers_link.book').label('count')) \
|
||||
entries = calibre_db.session.query(db.Publishers, func.count('books_publishers_link.book').label('count')) \
|
||||
.join(db.books_publishers_link).join(db.Books).filter(common_filters()) \
|
||||
.group_by(text('books_publishers_link.publisher')).order_by(db.Publishers.name).all()
|
||||
charlist = db.session.query(func.upper(func.substr(db.Publishers.name, 1, 1)).label('char')) \
|
||||
charlist = calibre_db.session.query(func.upper(func.substr(db.Publishers.name, 1, 1)).label('char')) \
|
||||
.join(db.books_publishers_link).join(db.Books).filter(common_filters()) \
|
||||
.group_by(func.upper(func.substr(db.Publishers.name, 1, 1))).all()
|
||||
return render_title_template('list.html', entries=entries, folder='web.books_list', charlist=charlist,
|
||||
@ -860,19 +861,19 @@ def publisher_list():
|
||||
def series_list():
|
||||
if current_user.check_visibility(constants.SIDEBAR_SERIES):
|
||||
if current_user.series_view == 'list':
|
||||
entries = db.session.query(db.Series, func.count('books_series_link.book').label('count')) \
|
||||
entries = calibre_db.session.query(db.Series, func.count('books_series_link.book').label('count')) \
|
||||
.join(db.books_series_link).join(db.Books).filter(common_filters()) \
|
||||
.group_by(text('books_series_link.series')).order_by(db.Series.sort).all()
|
||||
charlist = db.session.query(func.upper(func.substr(db.Series.sort, 1, 1)).label('char')) \
|
||||
charlist = calibre_db.session.query(func.upper(func.substr(db.Series.sort, 1, 1)).label('char')) \
|
||||
.join(db.books_series_link).join(db.Books).filter(common_filters()) \
|
||||
.group_by(func.upper(func.substr(db.Series.sort, 1, 1))).all()
|
||||
return render_title_template('list.html', entries=entries, folder='web.books_list', charlist=charlist,
|
||||
title=_(u"Series"), page="serieslist", data="series")
|
||||
else:
|
||||
entries = db.session.query(db.Books, func.count('books_series_link').label('count')) \
|
||||
entries = calibre_db.session.query(db.Books, func.count('books_series_link').label('count')) \
|
||||
.join(db.books_series_link).join(db.Series).filter(common_filters()) \
|
||||
.group_by(text('books_series_link.series')).order_by(db.Series.sort).all()
|
||||
charlist = db.session.query(func.upper(func.substr(db.Series.sort, 1, 1)).label('char')) \
|
||||
charlist = calibre_db.session.query(func.upper(func.substr(db.Series.sort, 1, 1)).label('char')) \
|
||||
.join(db.books_series_link).join(db.Books).filter(common_filters()) \
|
||||
.group_by(func.upper(func.substr(db.Series.sort, 1, 1))).all()
|
||||
|
||||
@ -886,9 +887,9 @@ def series_list():
|
||||
@login_required_if_no_ano
|
||||
def ratings_list():
|
||||
if current_user.check_visibility(constants.SIDEBAR_RATING):
|
||||
entries = db.session.query(db.Ratings, func.count('books_ratings_link.book').label('count'),
|
||||
entries = calibre_db.session.query(db.Ratings, func.count('books_ratings_link.book').label('count'),
|
||||
(db.Ratings.rating / 2).label('name')) \
|
||||
.join(db.books_ratings_link).join(db.Books).filter(common_filters()) \
|
||||
.join(calibre_db.books_ratings_link).join(db.Books).filter(common_filters()) \
|
||||
.group_by(text('books_ratings_link.rating')).order_by(db.Ratings.rating).all()
|
||||
return render_title_template('list.html', entries=entries, folder='web.books_list', charlist=list(),
|
||||
title=_(u"Ratings list"), page="ratingslist", data="ratings")
|
||||
@ -900,7 +901,7 @@ def ratings_list():
|
||||
@login_required_if_no_ano
|
||||
def formats_list():
|
||||
if current_user.check_visibility(constants.SIDEBAR_FORMAT):
|
||||
entries = db.session.query(db.Data, func.count('data.book').label('count'), db.Data.format.label('format')) \
|
||||
entries = calibre_db.session.query(db.Data, func.count('data.book').label('count'), db.Data.format.label('format')) \
|
||||
.join(db.Books).filter(common_filters()) \
|
||||
.group_by(db.Data.format).order_by(db.Data.format).all()
|
||||
return render_title_template('list.html', entries=entries, folder='web.books_list', charlist=list(),
|
||||
@ -922,13 +923,13 @@ def language_overview():
|
||||
cur_l = LC.parse(current_user.filter_language())
|
||||
except UnknownLocaleError:
|
||||
cur_l = None
|
||||
languages = db.session.query(db.Languages).filter(
|
||||
languages = calibre_db.session.query(db.Languages).filter(
|
||||
db.Languages.lang_code == current_user.filter_language()).all()
|
||||
if cur_l:
|
||||
languages[0].name = cur_l.get_language_name(get_locale())
|
||||
else:
|
||||
languages[0].name = _(isoLanguages.get(part3=languages[0].lang_code).name)
|
||||
lang_counter = db.session.query(db.books_languages_link,
|
||||
lang_counter = calibre_db.session.query(db.books_languages_link,
|
||||
func.count('books_languages_link.book').label('bookcount')).group_by(
|
||||
text('books_languages_link.lang_code')).all()
|
||||
return render_title_template('languages.html', languages=languages, lang_counter=lang_counter,
|
||||
@ -942,10 +943,10 @@ def language_overview():
|
||||
@login_required_if_no_ano
|
||||
def category_list():
|
||||
if current_user.check_visibility(constants.SIDEBAR_CATEGORY):
|
||||
entries = db.session.query(db.Tags, func.count('books_tags_link.book').label('count')) \
|
||||
entries = calibre_db.session.query(db.Tags, func.count('books_tags_link.book').label('count')) \
|
||||
.join(db.books_tags_link).join(db.Books).order_by(db.Tags.name).filter(common_filters()) \
|
||||
.group_by(text('books_tags_link.tag')).all()
|
||||
charlist = db.session.query(func.upper(func.substr(db.Tags.name, 1, 1)).label('char')) \
|
||||
charlist = calibre_db.session.query(func.upper(func.substr(db.Tags.name, 1, 1)).label('char')) \
|
||||
.join(db.books_tags_link).join(db.Books).filter(common_filters()) \
|
||||
.group_by(func.upper(func.substr(db.Tags.name, 1, 1))).all()
|
||||
return render_title_template('list.html', entries=entries, folder='web.books_list', charlist=charlist,
|
||||
@ -1003,8 +1004,8 @@ def search():
|
||||
def advanced_search():
|
||||
# Build custom columns names
|
||||
cc = get_cc_columns()
|
||||
db.session.connection().connection.connection.create_function("lower", 1, lcase)
|
||||
q = db.session.query(db.Books).filter(common_filters()).order_by(db.Books.sort)
|
||||
calibre_db.session.connection().connection.connection.create_function("lower", 1, lcase)
|
||||
q = calibre_db.session.query(db.Books).filter(common_filters()).order_by(db.Books.sort)
|
||||
|
||||
include_tag_inputs = request.args.getlist('include_tag')
|
||||
exclude_tag_inputs = request.args.getlist('exclude_tag')
|
||||
@ -1057,11 +1058,11 @@ def advanced_search():
|
||||
format='medium', locale=get_locale())])
|
||||
except ValueError:
|
||||
pub_start = u""
|
||||
tag_names = db.session.query(db.Tags).filter(db.Tags.id.in_(include_tag_inputs)).all()
|
||||
tag_names = calibre_db.session.query(db.Tags).filter(db.Tags.id.in_(include_tag_inputs)).all()
|
||||
searchterm.extend(tag.name for tag in tag_names)
|
||||
serie_names = db.session.query(db.Series).filter(db.Series.id.in_(include_series_inputs)).all()
|
||||
serie_names = calibre_db.session.query(db.Series).filter(db.Series.id.in_(include_series_inputs)).all()
|
||||
searchterm.extend(serie.name for serie in serie_names)
|
||||
language_names = db.session.query(db.Languages).filter(db.Languages.id.in_(include_languages_inputs)).all()
|
||||
language_names = calibre_db.session.query(db.Languages).filter(db.Languages.id.in_(include_languages_inputs)).all()
|
||||
if language_names:
|
||||
language_names = speaking_language(language_names)
|
||||
searchterm.extend(language.name for language in language_names)
|
||||
@ -1136,11 +1137,11 @@ def advanced_search():
|
||||
return render_title_template('search.html', adv_searchterm=searchterm,
|
||||
entries=q, title=_(u"search"), page="search")
|
||||
# prepare data for search-form
|
||||
tags = db.session.query(db.Tags).join(db.books_tags_link).join(db.Books).filter(common_filters()) \
|
||||
tags = calibre_db.session.query(db.Tags).join(db.books_tags_link).join(db.Books).filter(common_filters()) \
|
||||
.group_by(text('books_tags_link.tag')).order_by(db.Tags.name).all()
|
||||
series = db.session.query(db.Series).join(db.books_series_link).join(db.Books).filter(common_filters()) \
|
||||
series = calibre_db.session.query(db.Series).join(db.books_series_link).join(db.Books).filter(common_filters()) \
|
||||
.group_by(text('books_series_link.series')).order_by(db.Series.name).filter(common_filters()).all()
|
||||
extensions = db.session.query(db.Data).join(db.Books).filter(common_filters()) \
|
||||
extensions = calibre_db.session.query(db.Data).join(db.Books).filter(common_filters()) \
|
||||
.group_by(db.Data.format).order_by(db.Data.format).all()
|
||||
|
||||
if current_user.filter_language() == u"all":
|
||||
@ -1229,8 +1230,8 @@ def get_cover(book_id):
|
||||
@viewer_required
|
||||
def serve_book(book_id, book_format, anyname):
|
||||
book_format = book_format.split(".")[0]
|
||||
book = db.session.query(db.Books).filter(db.Books.id == book_id).first()
|
||||
data = db.session.query(db.Data).filter(db.Data.book == book.id).filter(db.Data.format == book_format.upper()) \
|
||||
book = calibre_db.session.query(db.Books).filter(db.Books.id == book_id).first()
|
||||
data = calibre_db.session.query(db.Data).filter(db.Data.book == book.id).filter(db.Data.format == book_format.upper()) \
|
||||
.first()
|
||||
log.info('Serving book: %s', data.name)
|
||||
if config.config_use_google_drive:
|
||||
@ -1522,9 +1523,9 @@ def profile():
|
||||
oauth_status = None
|
||||
|
||||
for book in current_user.downloads:
|
||||
downloadBook = db.session.query(db.Books).filter(db.Books.id == book.book_id).first()
|
||||
downloadBook = calibre_db.session.query(db.Books).filter(db.Books.id == book.book_id).first()
|
||||
if downloadBook:
|
||||
downloads.append(db.session.query(db.Books).filter(db.Books.id == book.book_id).first())
|
||||
downloads.append(calibre_db.session.query(db.Books).filter(db.Books.id == book.book_id).first())
|
||||
else:
|
||||
ub.delete_download(book.book_id)
|
||||
if request.method == "POST":
|
||||
@ -1603,7 +1604,7 @@ def profile():
|
||||
@login_required_if_no_ano
|
||||
@viewer_required
|
||||
def read_book(book_id, book_format):
|
||||
book = db.session.query(db.Books).filter(db.Books.id == book_id).filter(common_filters()).first()
|
||||
book = calibre_db.session.query(db.Books).filter(db.Books.id == book_id).filter(common_filters()).first()
|
||||
if not book:
|
||||
flash(_(u"Error opening eBook. File does not exist or file is not accessible:"), category="error")
|
||||
log.debug(u"Error opening eBook. File does not exist or file is not accessible:")
|
||||
@ -1627,7 +1628,7 @@ def read_book(book_id, book_format):
|
||||
else:
|
||||
for fileExt in constants.EXTENSIONS_AUDIO:
|
||||
if book_format.lower() == fileExt:
|
||||
entries = db.session.query(db.Books).filter(db.Books.id == book_id).filter(common_filters()).first()
|
||||
entries = calibre_db.session.query(db.Books).filter(db.Books.id == book_id).filter(common_filters()).first()
|
||||
log.debug(u"Start mp3 listening for %d", book_id)
|
||||
return render_title_template('listenmp3.html', mp3file=book_id, audioformat=book_format.lower(),
|
||||
title=_(u"Read a Book"), entry=entries, bookmark=bookmark)
|
||||
@ -1653,7 +1654,7 @@ def read_book(book_id, book_format):
|
||||
@web.route("/book/<int:book_id>")
|
||||
@login_required_if_no_ano
|
||||
def show_book(book_id):
|
||||
entries = db.session.query(db.Books).filter(and_(db.Books.id == book_id,
|
||||
entries = calibre_db.session.query(db.Books).filter(and_(db.Books.id == book_id,
|
||||
common_filters(allow_show_archived=True))).first()
|
||||
if entries:
|
||||
for index in range(0, len(entries.languages)):
|
||||
|
@ -24,10 +24,10 @@ import smtplib
|
||||
import socket
|
||||
import time
|
||||
import threading
|
||||
import queue
|
||||
from glob import glob
|
||||
from shutil import copyfile
|
||||
from datetime import datetime
|
||||
from sqlalchemy.exc import OperationalError
|
||||
|
||||
try:
|
||||
from StringIO import StringIO
|
||||
@ -46,7 +46,8 @@ from email.utils import make_msgid
|
||||
from email.generator import Generator
|
||||
from flask_babel import gettext as _
|
||||
|
||||
from . import db, logger, config
|
||||
from . import calibre_db, db
|
||||
from . import logger, config
|
||||
from .subproc_wrapper import process_open
|
||||
from . import gdriveutils
|
||||
|
||||
@ -190,6 +191,8 @@ class WorkerThread(threading.Thread):
|
||||
self.UIqueue = list()
|
||||
self.asyncSMTP = None
|
||||
self.id = 0
|
||||
self.db_queue = queue.Queue()
|
||||
calibre_db.add_queue(self.db_queue)
|
||||
self.doLock = threading.Lock()
|
||||
|
||||
# Main thread loop starting the different tasks
|
||||
@ -275,6 +278,18 @@ class WorkerThread(threading.Thread):
|
||||
self.doLock.acquire()
|
||||
index = self.current
|
||||
self.doLock.release()
|
||||
'''dbpath = os.path.join(config.config_calibre_dir, "metadata.db")
|
||||
engine = create_engine('sqlite://',
|
||||
echo=False,
|
||||
isolation_level="SERIALIZABLE",
|
||||
connect_args={'check_same_thread': True})
|
||||
engine.execute("attach database '{}' as calibre;".format(dbpath))
|
||||
conn = engine.connect()
|
||||
Session = scoped_session(sessionmaker(autocommit=False,
|
||||
autoflush=False,
|
||||
bind=engine))
|
||||
w_session = Session()
|
||||
engine.execute("attach database '{}' as calibre;".format(dbpath))'''
|
||||
file_path = self.queue[index]['file_path']
|
||||
bookid = self.queue[index]['bookid']
|
||||
format_old_ext = u'.' + self.queue[index]['settings']['old_book_format'].lower()
|
||||
@ -285,7 +300,7 @@ class WorkerThread(threading.Thread):
|
||||
# this will allow send to kindle workflow to continue to work
|
||||
if os.path.isfile(file_path + format_new_ext):
|
||||
log.info("Book id %d already converted to %s", bookid, format_new_ext)
|
||||
cur_book = db.session.query(db.Books).filter(db.Books.id == bookid).first()
|
||||
cur_book = calibre_db.session.query(db.Books).filter(db.Books.id == bookid).first()
|
||||
self.queue[index]['path'] = file_path
|
||||
self.queue[index]['title'] = cur_book.title
|
||||
self._handleSuccess()
|
||||
@ -309,19 +324,26 @@ class WorkerThread(threading.Thread):
|
||||
check, error_message = self._convert_calibre(file_path, format_old_ext, format_new_ext, index)
|
||||
|
||||
if check == 0:
|
||||
cur_book = db.session.query(db.Books).filter(db.Books.id == bookid).first()
|
||||
cur_book = calibre_db.session.query(db.Books).filter(db.Books.id == bookid).first()
|
||||
if os.path.isfile(file_path + format_new_ext):
|
||||
# self.db_queue.join()
|
||||
new_format = db.Data(name=cur_book.data[0].name,
|
||||
book_format=self.queue[index]['settings']['new_book_format'].upper(),
|
||||
book=bookid, uncompressed_size=os.path.getsize(file_path + format_new_ext))
|
||||
cur_book.data.append(new_format)
|
||||
task = {'task':'add_format','id': bookid, 'format': new_format}
|
||||
self.db_queue.put(task)
|
||||
# To Do how to handle error?
|
||||
print('finished')
|
||||
|
||||
'''cur_book.data.append(new_format)
|
||||
try:
|
||||
db.session.commit()
|
||||
# db.session.merge(cur_book)
|
||||
calibre_db.session.commit()
|
||||
except OperationalError as e:
|
||||
db.session.rollback()
|
||||
calibre_db.session.rollback()
|
||||
log.error("Database error: %s", e)
|
||||
self._handleError(_(u"Database error: %(error)s.", error=e))
|
||||
return
|
||||
return'''
|
||||
|
||||
self.queue[index]['path'] = cur_book.path
|
||||
self.queue[index]['title'] = cur_book.title
|
||||
@ -375,6 +397,7 @@ class WorkerThread(threading.Thread):
|
||||
# process returncode
|
||||
check = p.returncode
|
||||
calibre_traceback = p.stderr.readlines()
|
||||
error_message = ""
|
||||
for ele in calibre_traceback:
|
||||
if sys.version_info < (3, 0):
|
||||
ele = ele.decode('utf-8')
|
||||
|
Loading…
Reference in New Issue
Block a user