Cleanup Kobo integration
This commit is contained in:
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())
|
||||||
|
|
||||||
|
|
22
cps/admin.py
22
cps/admin.py
|
@ -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',
|
||||||
|
|
16
cps/kobo.py
16
cps/kobo.py
|
@ -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)
|
||||||
|
|
12
cps/web.py
12
cps/web.py
|
@ -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…
Reference in New Issue
Block a user