Cleanup Kobo integration

pull/1139/head
Ozzieisaacs 5 years ago
parent 3e404101bd
commit cd9bb56db5

@ -68,7 +68,6 @@ _VERSIONS = OrderedDict(
Flask_SimpleLDAP = u'installed' if bool(services.ldap) else u'not installed', Flask_SimpleLDAP = u'installed' if bool(services.ldap) else u'not installed',
Goodreads = u'installed' if bool(services.goodreads_support) else u'not installed', Goodreads = u'installed' if bool(services.goodreads_support) else u'not installed',
jsonschema = services.SyncToken.__version__ if bool(services.SyncToken) else u'not installed', jsonschema = services.SyncToken.__version__ if bool(services.SyncToken) else u'not installed',
) )
_VERSIONS.update(uploader.get_versions()) _VERSIONS.update(uploader.get_versions())

@ -64,7 +64,6 @@ except ImportError:
oauth_check = {} oauth_check = {}
feature_support['gdrive'] = gdrive_support feature_support['gdrive'] = gdrive_support
admi = Blueprint('admin', __name__) admi = Blueprint('admin', __name__)
log = logger.create() log = logger.create()
@ -491,7 +490,6 @@ def _configuration_update_helper():
db_change = False db_change = False
to_save = request.form.to_dict() to_save = request.form.to_dict()
# _config_dict = lambda x: config.set_from_dictionary(to_save, x, lambda y: y['id'])
_config_string = lambda x: config.set_from_dictionary(to_save, x, lambda y: y.strip() if y else y) _config_string = lambda x: config.set_from_dictionary(to_save, x, lambda y: y.strip() if y else y)
_config_int = lambda x: config.set_from_dictionary(to_save, x, int) _config_int = lambda x: config.set_from_dictionary(to_save, x, int)
_config_checkbox = lambda x: config.set_from_dictionary(to_save, x, lambda y: y == "on", False) _config_checkbox = lambda x: config.set_from_dictionary(to_save, x, lambda y: y == "on", False)
@ -531,8 +529,6 @@ def _configuration_update_helper():
if config.config_certfile and not os.path.isfile(config.config_certfile): if config.config_certfile and not os.path.isfile(config.config_certfile):
return _configuration_result('Certfile location is not valid, please enter correct path', gdriveError) return _configuration_result('Certfile location is not valid, please enter correct path', gdriveError)
_config_string("config_server_url")
_config_checkbox_int("config_uploading") _config_checkbox_int("config_uploading")
_config_checkbox_int("config_anonbrowse") _config_checkbox_int("config_anonbrowse")
_config_checkbox_int("config_public_reg") _config_checkbox_int("config_public_reg")
@ -845,24 +841,6 @@ def edit_user(user_id):
content.default_language = to_save["default_language"] content.default_language = to_save["default_language"]
if "locale" in to_save and to_save["locale"]: if "locale" in to_save and to_save["locale"]:
content.locale = to_save["locale"] content.locale = to_save["locale"]
if "kobo_user_key" in to_save and to_save["kobo_user_key"]:
kobo_user_key_hash = generate_password_hash(to_save["kobo_user_key"])
if kobo_user_key_hash != content.kobo_user_key_hash:
existing_kobo_user_key = ub.session.query(ub.User).filter(ub.User.kobo_user_key_hash == kobo_user_key_hash).first()
if not existing_kobo_user_key:
content.kobo_user_key_hash = kobo_user_key_hash
else:
flash(_(u"Found an existing account for this Kobo UserKey."), category="error")
return render_title_template("user_edit.html",
translations=translations,
languages=languages,
new_user=0,
content=content,
downloads=downloads,
registered_oauth=oauth_check,
feature_support=feature_support,
title=_(u"Edit User %(nick)s", nick=content.nickname), page="edituser")
if to_save["email"] and to_save["email"] != content.email: if to_save["email"] and to_save["email"] != content.email:
existing_email = ub.session.query(ub.User).filter(ub.User.email == to_save["email"].lower()) \ existing_email = ub.session.query(ub.User).filter(ub.User.email == to_save["email"].lower()) \
.first() .first()

@ -49,7 +49,6 @@ class _Settings(_Base):
config_port = Column(Integer, default=constants.DEFAULT_PORT) config_port = Column(Integer, default=constants.DEFAULT_PORT)
config_certfile = Column(String) config_certfile = Column(String)
config_keyfile = Column(String) config_keyfile = Column(String)
config_server_url = Column(String, default='')
config_calibre_web_title = Column(String, default=u'Calibre-Web') config_calibre_web_title = Column(String, default=u'Calibre-Web')
config_books_per_page = Column(Integer, default=60) config_books_per_page = Column(Integer, default=60)
@ -313,7 +312,6 @@ def _migrate_table(session, orm_class):
if changed: if changed:
session.commit() session.commit()
session.query
def autodetect_calibre_binary(): def autodetect_calibre_binary():
if sys.platform == "win32": if sys.platform == "win32":

@ -106,7 +106,6 @@ except ValueError:
del env_CALIBRE_PORT del env_CALIBRE_PORT
EXTENSIONS_AUDIO = {'mp3', 'm4a', 'm4b'} EXTENSIONS_AUDIO = {'mp3', 'm4a', 'm4b'}
EXTENSIONS_CONVERT = {'pdf', 'epub', 'mobi', 'azw3', 'docx', 'rtf', 'fb2', 'lit', 'lrf', 'txt', 'htmlz', 'rtf', 'odt'} EXTENSIONS_CONVERT = {'pdf', 'epub', 'mobi', 'azw3', 'docx', 'rtf', 'fb2', 'lit', 'lrf', 'txt', 'htmlz', 'rtf', 'odt'}
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',

@ -40,7 +40,8 @@ from werkzeug.datastructures import Headers
from sqlalchemy import func from sqlalchemy import func
import requests import requests
from . import config, logger, kobo_auth, db, helper, services from . import config, logger, kobo_auth, db, helper
from .services import SyncToken as SyncToken
from .web import download_required from .web import download_required
KOBO_FORMATS = {"KEPUB": ["KEPUB"], "EPUB": ["EPUB", "EPUB3"]} KOBO_FORMATS = {"KEPUB": ["KEPUB"], "EPUB": ["EPUB", "EPUB3"]}
@ -72,6 +73,8 @@ CONNECTION_SPECIFIC_HEADERS = [
def redirect_or_proxy_request(): def redirect_or_proxy_request():
if request.method == "GET": if request.method == "GET":
return redirect(get_store_url_for_current_request(), 307) return redirect(get_store_url_for_current_request(), 307)
if request.method == "DELETE":
return make_response(jsonify({}))
else: else:
# The Kobo device turns other request types into GET requests on redirects, so we instead proxy to the Kobo store ourselves. # The Kobo device turns other request types into GET requests on redirects, so we instead proxy to the Kobo store ourselves.
outgoing_headers = Headers(request.headers) outgoing_headers = Headers(request.headers)
@ -97,7 +100,7 @@ def redirect_or_proxy_request():
@login_required @login_required
@download_required @download_required
def HandleSyncRequest(): def HandleSyncRequest():
sync_token = services.SyncToken.from_headers(request.headers) sync_token = SyncToken.SyncToken.from_headers(request.headers)
log.info("Kobo library sync request received.") log.info("Kobo library sync request received.")
# TODO: Limit the number of books return per sync call, and rely on the sync-continuatation header # TODO: Limit the number of books return per sync call, and rely on the sync-continuatation header
@ -117,7 +120,7 @@ def HandleSyncRequest():
changed_entries = ( changed_entries = (
db.session.query(db.Books) db.session.query(db.Books)
.join(db.Data) .join(db.Data)
.filter(func.datetime(db.Books.last_modified) > sync_token.books_last_modified) .filter(func.datetime(db.Books.last_modified) != sync_token.books_last_modified)
.filter(db.Data.format.in_(KOBO_FORMATS)) .filter(db.Data.format.in_(KOBO_FORMATS))
.all() .all()
) )
@ -322,11 +325,10 @@ def reading_state(book):
return reading_state return reading_state
@kobo.route( @kobo.route("/<book_uuid>/image.jpg")
"/<book_uuid>/image.jpg"
)
@login_required @login_required
def HandleCoverImageRequest(book_uuid): def HandleCoverImageRequest(book_uuid):
log.debug("Cover request received for book %s" % book_uuid)
book_cover = helper.get_book_cover_with_uuid( book_cover = helper.get_book_cover_with_uuid(
book_uuid, use_generic_cover_on_failure=False book_uuid, use_generic_cover_on_failure=False
) )
@ -346,7 +348,7 @@ def TopLevelEndpoint():
@kobo.route("/v1/library/tags", methods=["POST"]) @kobo.route("/v1/library/tags", methods=["POST"])
@kobo.route("/v1/library/tags/<shelf_name>", methods=["POST"]) @kobo.route("/v1/library/tags/<shelf_name>", methods=["POST"])
@kobo.route("/v1/library/tags/<tag_id>", methods=["DELETE"]) @kobo.route("/v1/library/tags/<tag_id>", methods=["DELETE"])
def HandleUnimplementedRequest(book_uuid=None, shelf_name=None, tag_id=None): def HandleUnimplementedRequest(dummy=None, book_uuid=None, shelf_name=None, tag_id=None):
return redirect_or_proxy_request() return redirect_or_proxy_request()

@ -42,7 +42,7 @@ def to_epoch_timestamp(datetime_object):
return (datetime_object - datetime(1970, 1, 1)).total_seconds() return (datetime_object - datetime(1970, 1, 1)).total_seconds()
class SyncToken: class SyncToken():
""" The SyncToken is used to persist state accross requests. """ The SyncToken is used to persist state accross requests.
When serialized over the response headers, the Kobo device will propagate the token onto following requests to the service. When serialized over the response headers, the Kobo device will propagate the token onto following requests to the service.
As an example use-case, the SyncToken is used to detect books that have been added to the library since the last time the device synced to the server. As an example use-case, the SyncToken is used to detect books that have been added to the library since the last time the device synced to the server.

@ -104,10 +104,6 @@
<!--option-- value="3" {% if config.config_updatechannel == 3 %}selected{% endif %}>{{_('Nightly (Automatic)')}}</option--> <!--option-- value="3" {% if config.config_updatechannel == 3 %}selected{% endif %}>{{_('Nightly (Automatic)')}}</option-->
</select> </select>
</div> </div>
<div class="form-group">
<label for="config_server_url">{{_('Server Url. This is only used for the (experimental) Kobo device library sync')}}</label>
<input type="text" class="form-control" name="config_server_url" id="config_server_url" value="{% if config.config_server_url != None %}{{ config.config_server_url }}{% endif %}" autocomplete="off">
</div>
</div> </div>
</div> </div>
</div> </div>

@ -27,10 +27,6 @@
<input type="email" class="form-control" name="kindle_mail" id="kindle_mail" value="{{ content.kindle_mail if content.kindle_mail != None }}"> <input type="email" class="form-control" name="kindle_mail" id="kindle_mail" value="{{ content.kindle_mail if content.kindle_mail != None }}">
</div> </div>
<div class="form-group"> <div class="form-group">
<div class="form-group">
<label for="kobo_user_key">{{_('KoboStore UserKey')}}</label>
<input type="password" class="form-control" name="kobo_user_key" id="kobo_user_key" value="" autocomplete="off">
</div>
<label for="locale">{{_('Language')}}</label> <label for="locale">{{_('Language')}}</label>
<select name="locale" id="locale" class="form-control"> <select name="locale" id="locale" class="form-control">
{% for translation in translations %} {% for translation in translations %}

@ -330,7 +330,7 @@ class RemoteAuthToken(Base):
__tablename__ = 'remote_auth_token' __tablename__ = 'remote_auth_token'
id = Column(Integer, primary_key=True) id = Column(Integer, primary_key=True)
auth_token = Column(String, unique=True) # IMPORTANT: ToDo:check length restríction id not valid for string auth_token = Column(String, unique=True)
user_id = Column(Integer, ForeignKey('user.id')) user_id = Column(Integer, ForeignKey('user.id'))
verified = Column(Boolean, default=False) verified = Column(Boolean, default=False)
expiration = Column(DateTime) expiration = Column(DateTime)

@ -250,6 +250,7 @@ def edit_required(f):
return inner return inner
# ################################### Helper functions ################################################################ # ################################### Helper functions ################################################################
@ -460,12 +461,6 @@ def get_matching_tags():
if len(exclude_tag_inputs) > 0: if len(exclude_tag_inputs) > 0:
for tag in exclude_tag_inputs: for tag in exclude_tag_inputs:
q = q.filter(not_(db.Books.tags.any(db.Tags.id == tag))) q = q.filter(not_(db.Books.tags.any(db.Tags.id == tag)))
'''if len(include_extension_inputs) > 0:
for tag in exclude_tag_inputs:
q = q.filter(not_(db.Books.tags.any(db.Tags.id == tag)))
if len(exclude_extension_inputs) > 0:
for tag in exclude_tag_inputs:
q = q.filter(not_(db.Books.tags.any(db.Tags.id == tag)))'''
for book in q: for book in q:
for tag in book.tags: for tag in book.tags:
if tag.id not in tag_dict['tags']: if tag.id not in tag_dict['tags']:
@ -1048,9 +1043,6 @@ def serve_book(book_id, book_format, anyname):
@login_required_if_no_ano @login_required_if_no_ano
@download_required @download_required
def download_link(book_id, book_format): def download_link(book_id, book_format):
if book_format.lower() == "kepub":
book_format= "epub"
log.info("Book %s in format %s downloaded", str(book_id), book_format)
return get_download_link(book_id, book_format) return get_download_link(book_id, book_format)
@ -1092,10 +1084,10 @@ def register():
if not to_save["nickname"] or not to_save["email"]: if not to_save["nickname"] or not to_save["email"]:
flash(_(u"Please fill out all fields!"), category="error") flash(_(u"Please fill out all fields!"), category="error")
return render_title_template('register.html', title=_(u"register"), page="register") return render_title_template('register.html', title=_(u"register"), page="register")
existing_user = ub.session.query(ub.User).filter(func.lower(ub.User.nickname) == to_save["nickname"] existing_user = ub.session.query(ub.User).filter(func.lower(ub.User.nickname) == to_save["nickname"]
.lower()).first() .lower()).first()
existing_email = ub.session.query(ub.User).filter(ub.User.email == to_save["email"].lower()).first() existing_email = ub.session.query(ub.User).filter(ub.User.email == to_save["email"].lower()).first()
if not existing_user and not existing_email: if not existing_user and not existing_email:
content = ub.User() content = ub.User()
# content.password = generate_password_hash(to_save["password"]) # content.password = generate_password_hash(to_save["password"])

Loading…
Cancel
Save