Books are removed from synced books upon archiving (from kobo or calibre-web side)
unicode texts (title, author) are showing up right on kobo reader Added some missing kobo routes (prevents 404 response) Added a lot of debug output on kobo sync requests
This commit is contained in:
parent
87e526642c
commit
7640ac1b3b
37
cps/kobo.py
37
cps/kobo.py
|
@ -22,6 +22,7 @@ import datetime
|
||||||
import os
|
import os
|
||||||
import uuid
|
import uuid
|
||||||
from time import gmtime, strftime
|
from time import gmtime, strftime
|
||||||
|
import json
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from urllib import unquote
|
from urllib import unquote
|
||||||
|
@ -102,6 +103,8 @@ def make_request_to_kobo_store(sync_token=None):
|
||||||
allow_redirects=False,
|
allow_redirects=False,
|
||||||
timeout=(2, 10)
|
timeout=(2, 10)
|
||||||
)
|
)
|
||||||
|
log.debug("Content: " + str(store_response.content))
|
||||||
|
log.debug("StatusCode: " + str(store_response.status_code))
|
||||||
return store_response
|
return store_response
|
||||||
|
|
||||||
|
|
||||||
|
@ -110,7 +113,8 @@ 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)
|
||||||
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.
|
||||||
store_response = make_request_to_kobo_store()
|
store_response = make_request_to_kobo_store()
|
||||||
|
|
||||||
response_headers = store_response.headers
|
response_headers = store_response.headers
|
||||||
|
@ -205,8 +209,8 @@ def HandleSyncRequest():
|
||||||
books = calibre_db.session.execute(changed_entries.limit(SYNC_ITEM_LIMIT))
|
books = calibre_db.session.execute(changed_entries.limit(SYNC_ITEM_LIMIT))
|
||||||
else:
|
else:
|
||||||
books = changed_entries.limit(SYNC_ITEM_LIMIT)
|
books = changed_entries.limit(SYNC_ITEM_LIMIT)
|
||||||
|
log.debug("Books to Sync: {}".format(books.count()))
|
||||||
for book in books:
|
for book in books:
|
||||||
kobo_sync_status.add_synced_books(book.Books.id)
|
|
||||||
formats = [data.format for data in book.Books.data]
|
formats = [data.format for data in book.Books.data]
|
||||||
if not 'KEPUB' in formats and config.config_kepubifypath and 'EPUB' in formats:
|
if not 'KEPUB' in formats and config.config_kepubifypath and 'EPUB' in formats:
|
||||||
helper.convert_book_format(book.Books.id, config.config_calibre_dir, 'EPUB', 'KEPUB', current_user.name)
|
helper.convert_book_format(book.Books.id, config.config_calibre_dir, 'EPUB', 'KEPUB', current_user.name)
|
||||||
|
@ -245,6 +249,7 @@ def HandleSyncRequest():
|
||||||
pass
|
pass
|
||||||
|
|
||||||
new_books_last_created = max(ts_created, new_books_last_created)
|
new_books_last_created = max(ts_created, new_books_last_created)
|
||||||
|
kobo_sync_status.add_synced_books(book.Books.id)
|
||||||
|
|
||||||
if sqlalchemy_version2:
|
if sqlalchemy_version2:
|
||||||
max_change = calibre_db.session.execute(changed_entries
|
max_change = calibre_db.session.execute(changed_entries
|
||||||
|
@ -330,9 +335,10 @@ def generate_sync_response(sync_token, sync_results, set_cont=False):
|
||||||
extra_headers["x-kobo-sync"] = "continue"
|
extra_headers["x-kobo-sync"] = "continue"
|
||||||
sync_token.to_headers(extra_headers)
|
sync_token.to_headers(extra_headers)
|
||||||
|
|
||||||
# log.debug("Kobo Sync Content: {}".format(sync_results))
|
log.debug("Kobo Sync Content: {}".format(sync_results))
|
||||||
response = make_response(jsonify(sync_results), extra_headers)
|
# jsonify decodes the unicode string different to what kobo expects
|
||||||
|
response = make_response(json.dumps(sync_results), extra_headers)
|
||||||
|
response.headers["Content-Type"] = "application/json; charset=utf-8"
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
@ -377,7 +383,7 @@ def get_download_url_for_book(book, book_format):
|
||||||
|
|
||||||
|
|
||||||
def create_book_entitlement(book, archived):
|
def create_book_entitlement(book, archived):
|
||||||
book_uuid = book.uuid
|
book_uuid = str(book.uuid)
|
||||||
return {
|
return {
|
||||||
"Accessibility": "Full",
|
"Accessibility": "Full",
|
||||||
"ActivePeriod": {"From": convert_to_kobo_timestamp_string(datetime.datetime.now())},
|
"ActivePeriod": {"From": convert_to_kobo_timestamp_string(datetime.datetime.now())},
|
||||||
|
@ -404,7 +410,6 @@ def get_description(book):
|
||||||
return book.comments[0].text
|
return book.comments[0].text
|
||||||
|
|
||||||
|
|
||||||
# TODO handle multiple authors
|
|
||||||
def get_author(book):
|
def get_author(book):
|
||||||
if not book.authors:
|
if not book.authors:
|
||||||
return {"Contributors": None}
|
return {"Contributors": None}
|
||||||
|
@ -412,10 +417,11 @@ def get_author(book):
|
||||||
author_list = []
|
author_list = []
|
||||||
autor_roles = []
|
autor_roles = []
|
||||||
for author in book.authors:
|
for author in book.authors:
|
||||||
autor_roles.append({"Name":author.name, "Role":"Author"})
|
autor_roles.append({"Name":author.name}) #.encode('unicode-escape').decode('latin-1')
|
||||||
author_list.append(author.name)
|
author_list.append(author.name)
|
||||||
return {"ContributorRoles": autor_roles, "Contributors":author_list}
|
return {"ContributorRoles": autor_roles, "Contributors":author_list}
|
||||||
return {"ContributorRoles": [{"Name":book.authors[0].name, "Role":"Author"}], "Contributors": book.authors[0].name}
|
return {"ContributorRoles": [{"Name":book.authors[0].name}],
|
||||||
|
"Contributors": book.authors[0].name}
|
||||||
|
|
||||||
|
|
||||||
def get_publisher(book):
|
def get_publisher(book):
|
||||||
|
@ -472,9 +478,7 @@ def get_metadata(book):
|
||||||
"IsSocialEnabled": True,
|
"IsSocialEnabled": True,
|
||||||
"Language": "en",
|
"Language": "en",
|
||||||
"PhoneticPronunciations": {},
|
"PhoneticPronunciations": {},
|
||||||
# TODO: Fix book.pubdate to return a datetime object so that we can easily
|
"PublicationDate": convert_to_kobo_timestamp_string(book.pubdate),
|
||||||
# convert it to the format Kobo devices expect.
|
|
||||||
"PublicationDate": book.pubdate,
|
|
||||||
"Publisher": {"Imprint": "", "Name": get_publisher(book),},
|
"Publisher": {"Imprint": "", "Name": get_publisher(book),},
|
||||||
"RevisionId": book_uuid,
|
"RevisionId": book_uuid,
|
||||||
"Title": book.title,
|
"Title": book.title,
|
||||||
|
@ -489,7 +493,7 @@ def get_metadata(book):
|
||||||
"Number": get_seriesindex(book), # ToDo Check int() ?
|
"Number": get_seriesindex(book), # ToDo Check int() ?
|
||||||
"NumberFloat": float(get_seriesindex(book)),
|
"NumberFloat": float(get_seriesindex(book)),
|
||||||
# Get a deterministic id based on the series name.
|
# Get a deterministic id based on the series name.
|
||||||
"Id": uuid.uuid3(uuid.NAMESPACE_DNS, name),
|
"Id": str(uuid.uuid3(uuid.NAMESPACE_DNS, name)),
|
||||||
}
|
}
|
||||||
|
|
||||||
return metadata
|
return metadata
|
||||||
|
@ -958,6 +962,8 @@ def HandleBookDeletionRequest(book_uuid):
|
||||||
|
|
||||||
ub.session.merge(archived_book)
|
ub.session.merge(archived_book)
|
||||||
ub.session_commit()
|
ub.session_commit()
|
||||||
|
if archived_book.is_archived:
|
||||||
|
kobo_sync_status.remove_synced_book(book_id)
|
||||||
return "", 204
|
return "", 204
|
||||||
|
|
||||||
|
|
||||||
|
@ -986,11 +992,16 @@ def HandleUserRequest(dummy=None):
|
||||||
@kobo.route("/v1/products/<dummy>/recommendations", methods=["GET", "POST"])
|
@kobo.route("/v1/products/<dummy>/recommendations", methods=["GET", "POST"])
|
||||||
@kobo.route("/v1/products/<dummy>/nextread", methods=["GET", "POST"])
|
@kobo.route("/v1/products/<dummy>/nextread", methods=["GET", "POST"])
|
||||||
@kobo.route("/v1/products/<dummy>/reviews", methods=["GET", "POST"])
|
@kobo.route("/v1/products/<dummy>/reviews", methods=["GET", "POST"])
|
||||||
|
@kobo.route("/v1/products/featured/<dummy>", methods=["GET", "POST"])
|
||||||
|
@kobo.route("/v1/products/featured/", methods=["GET", "POST"])
|
||||||
@kobo.route("/v1/products/books/external/<dummy>", methods=["GET", "POST"])
|
@kobo.route("/v1/products/books/external/<dummy>", methods=["GET", "POST"])
|
||||||
@kobo.route("/v1/products/books/series/<dummy>", methods=["GET", "POST"])
|
@kobo.route("/v1/products/books/series/<dummy>", methods=["GET", "POST"])
|
||||||
@kobo.route("/v1/products/books/<dummy>", methods=["GET", "POST"])
|
@kobo.route("/v1/products/books/<dummy>", methods=["GET", "POST"])
|
||||||
|
@kobo.route("/v1/products/books/<dummy>/", methods=["GET", "POST"])
|
||||||
@kobo.route("/v1/products/dailydeal", methods=["GET", "POST"])
|
@kobo.route("/v1/products/dailydeal", methods=["GET", "POST"])
|
||||||
|
@kobo.route("/v1/products/deals", methods=["GET", "POST"])
|
||||||
@kobo.route("/v1/products", methods=["GET", "POST"])
|
@kobo.route("/v1/products", methods=["GET", "POST"])
|
||||||
|
@kobo.route("/v1/affiliate", methods=["GET", "POST"])
|
||||||
def HandleProductsRequest(dummy=None):
|
def HandleProductsRequest(dummy=None):
|
||||||
log.debug("Unimplemented Products Request received: %s", request.base_url)
|
log.debug("Unimplemented Products Request received: %s", request.base_url)
|
||||||
return redirect_or_proxy_request()
|
return redirect_or_proxy_request()
|
||||||
|
|
|
@ -54,6 +54,7 @@ from .helper import check_valid_domain, render_task_status, check_email, check_u
|
||||||
from .pagination import Pagination
|
from .pagination import Pagination
|
||||||
from .redirect import redirect_back
|
from .redirect import redirect_back
|
||||||
from .usermanagement import login_required_if_no_ano
|
from .usermanagement import login_required_if_no_ano
|
||||||
|
from .kobo_sync_status import remove_synced_book
|
||||||
from .render_template import render_title_template
|
from .render_template import render_title_template
|
||||||
|
|
||||||
feature_support = {
|
feature_support = {
|
||||||
|
@ -206,6 +207,8 @@ def toggle_archived(book_id):
|
||||||
archived_book.is_archived = True
|
archived_book.is_archived = True
|
||||||
ub.session.merge(archived_book)
|
ub.session.merge(archived_book)
|
||||||
ub.session_commit("Book {} archivebit toggled".format(book_id))
|
ub.session_commit("Book {} archivebit toggled".format(book_id))
|
||||||
|
if archived_book.is_archived:
|
||||||
|
remove_synced_book(book_id)
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user