Exemplo n.º 1
0
def sync() -> flask.Response:
    extension_version = flask.request.headers.get(
        "Quarchive-Extension-Version", "unknown"
    )
    log.debug("extension version: %s", extension_version)
    user = get_current_user()
    use_jsonlines = flask.request.headers["Content-Type"] != "application/json"
    if not use_jsonlines:
        log.warning("sync request using deprecated single json object")
        body = flask.request.json
        recieved_bookmarks = (Bookmark.from_json(item) for item in body["bookmarks"])
    else:
        log.info("sync request using jsonlines")
        recieved_bookmarks = (
            Bookmark.from_json(json.loads(l)) for l in flask.request.stream.readlines()
        )

    try:
        changed_bookmarks = merge_bookmarks(
            db.session, user.user_uuid, recieved_bookmarks
        )
    except BadCanonicalisationException as e:
        log.error(
            "bad canonicalised url ('%s') from version %s, user %s",
            e.url_string,
            extension_version,
            user,
        )
        db.session.rollback()
        flask.abort(400, "bad canonicalisation on url: %s" % e.url_string)
    db.session.commit()
    if "full" in flask.request.args:
        response_bookmarks = all_bookmarks(db.session, get_current_user().user_uuid)
    else:
        response_bookmarks = changed_bookmarks

    # If we got JSON, send json back
    if not use_jsonlines:
        return flask.json.jsonify(
            {"bookmarks": [b.to_json() for b in response_bookmarks]}
        )
    else:

        def generator():
            for b in response_bookmarks:
                yield json.dumps(b.to_json())
                yield "\n"

        return flask.Response(
            flask.stream_with_context(generator()), mimetype="application/x-ndjson",
        )
Exemplo n.º 2
0
def sync(current_user: User) -> Tuple[flask.Response, int]:
    start_time = datetime.utcnow()
    extension_version = flask.request.headers.get(
        "Quarchive-Extension-Version", "unknown"
    )
    log.debug("extension version: %s", extension_version)
    user_uuid = current_user.user_uuid
    use_jsonlines = flask.request.headers["Content-Type"] != "application/json"
    if not use_jsonlines:
        log.warning("sync request using deprecated single json object")
        body = flask.request.json
        recieved_bookmarks = (Bookmark.from_json(item) for item in body["bookmarks"])
    else:
        log.info("sync request using jsonlines")
        recieved_bookmarks = (
            Bookmark.from_json(json.loads(l)) for l in flask.request.stream.readlines()
        )

    try:
        merge_result = merge_bookmarks(db.session, user_uuid, recieved_bookmarks)
    except BadCanonicalisationException as e:
        log.error(
            "bad canonicalised url ('%s') from version %s, user %s",
            e.url_string,
            extension_version,
            current_user,
        )
        db.session.rollback()
        flask.abort(400, "bad canonicalisation on url: %s" % e.url_string)
    db.session.commit()

    for added in merge_result.added:
        publish_message(
            message_lib.BookmarkCreated(
                user_uuid=user_uuid, url_uuid=added.url.url_uuid
            ),
            environ["QM_RABBITMQ_BG_WORKER_TOPIC"],
        )

    is_full_sync = "full" in flask.request.args

    if is_full_sync:
        response_bookmarks = all_bookmarks(db.session, current_user.user_uuid)
    else:
        response_bookmarks = merge_result.changed

    # If we got JSON, send json back
    if not use_jsonlines:
        return flask.json.jsonify(
            {"bookmarks": [b.to_json() for b in response_bookmarks]}
        )
    else:

        def generator():
            for b in response_bookmarks:
                yield json.dumps(b.to_json())
                yield "\n"
            if is_full_sync:
                duration = datetime.utcnow() - start_time
                log.info(
                    "completed full sync for %s in %ds",
                    current_user.username,
                    duration.total_seconds(),
                )

        return (
            flask.Response(
                flask.stream_with_context(generator()), mimetype="application/x-ndjson",
            ),
            200,
        )