diff --git a/cps/kobo.py b/cps/kobo.py index d78e6f19..dce6869a 100644 --- a/cps/kobo.py +++ b/cps/kobo.py @@ -1,27 +1,22 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- -from flask import Blueprint, request, flash, redirect, url_for -from . import config, logger, kobo_auth, ub, db, helper -from .web import download_required -from flask import make_response -from flask import jsonify -from flask import json -from flask import send_file -from time import gmtime, strftime +import copy import uuid -from uuid import uuid4, uuid3 -from collections import defaultdict +import os +from datetime import datetime, tzinfo, timedelta +from time import gmtime, strftime + from b2sdk.account_info.in_memory import InMemoryAccountInfo from b2sdk.api import B2Api -import os -import subprocess -from datetime import datetime, tzinfo, timedelta -from .constants import CONFIG_DIR as _CONFIG_DIR -import copy -import jsonschema -from sqlalchemy import func +from jsonschema import validate, exceptions +from flask import Blueprint, request, make_response, jsonify, json, send_file from flask_login import login_required +from sqlalchemy import func + +from . import config, logger, kobo_auth, ub, db, helper +from .constants import CONFIG_DIR as _CONFIG_DIR +from .web import download_required B2_SECRETS = os.path.join(_CONFIG_DIR, "b2_secrets.json") @@ -32,6 +27,7 @@ log = logger.create() import base64 + def b64encode(data): return base64.b64encode(data) @@ -100,13 +96,13 @@ class SyncToken: base64.b64decode(sync_token_header + "=" * (-len(sync_token_header) % 4)) ) try: - jsonschema.validate(sync_token_json, SyncToken.token_schema) + validate(sync_token_json, SyncToken.token_schema) if sync_token_json["version"] < SyncToken.MIN_VERSION: raise ValueError data_json = sync_token_json["data"] - jsonschema.validate(sync_token_json, SyncToken.data_schema_v1) - except (jsonschema.exceptions.ValidationError, ValueError) as e: + validate(sync_token_json, SyncToken.data_schema_v1) + except (exceptions.ValidationError, ValueError) as e: log.error("Sync token contents do not follow the expected json schema.") return SyncToken() @@ -219,8 +215,12 @@ def get_metadata__v1(book_uuid): ] return jsonify([metadata]) + def get_download_url_for_book(book): - return "{url_base}/download/{book_id}/kepub".format(url_base=config.config_server_url, book_id=book.id) + return "{url_base}/download/{book_id}/kepub".format( + url_base=config.config_server_url, book_id=book.id + ) + def get_download_url_for_book_b2(book): # TODO: Research what formats Kobo will support over the sync protocol. @@ -365,7 +365,7 @@ def create_metadata(book): "Number": book.series_index, "NumberFloat": float(book.series_index), # Get a deterministic id based on the series name. - "Id": uuid3(uuid.NAMESPACE_DNS, get_series(book).encode("utf-8")), + "Id": uuid.uuid3(uuid.NAMESPACE_DNS, get_series(book).encode("utf-8")), } return metadata @@ -436,7 +436,7 @@ def HandleDummyRequest(dummy=None): @kobo.route("/v1/auth/device", methods=["POST"]) def HandleAuthRequest(): - # Missing feature: Authentication :) + # This AuthRequest isn't used for most of our usecases. response = make_response( jsonify( { diff --git a/cps/kobo_auth.py b/cps/kobo_auth.py index c1f45f08..2fbd230d 100644 --- a/cps/kobo_auth.py +++ b/cps/kobo_auth.py @@ -46,14 +46,17 @@ Some possible alternatives that require more research: from functools import wraps from flask import request, make_response from werkzeug.security import check_password_hash + from . import logger, ub, lm USER_KEY_HEADER = "x-kobo-userkey" log = logger.create() + def disable_failed_auth_redirect_for_blueprint(bp): lm.blueprint_login_views[bp.name] = None + @lm.request_loader def load_user_from_kobo_request(request): user_key = request.headers.get(USER_KEY_HEADER) @@ -64,4 +67,4 @@ def load_user_from_kobo_request(request): if check_password_hash(str(user.kobo_user_key_hash), user_key): return user log.info("Received Kobo request without a recognizable UserKey.") - return None \ No newline at end of file + return None