Files
bookish/bookish/routes/api.py
T
truetype c1421665c0 feat: persistent SQLite storage for bookmarks + positions keyed by content_hash
- new bookish/services/database.py: SQLite with WAL mode, tables for
  bookmarks and reading_positions, keyed by content_hash (SHA256)
- new bookish/routes/api.py: REST endpoints for CRUD bookmarks
  and save/load reading position
- upload endpoint returns content_hash (SHA256 of file)
- reader route computes SHA256 and passes BOOKISH_HASH to template
- reader.js: bookmarks + positions use API server as primary storage
  with localStorage fallback for offline/resilience
- position saves debounced (1.5s) to avoid hammering server
- .gitignore: added bookish.db
2026-07-23 22:35:04 +02:00

58 lines
1.6 KiB
Python

import time
from flask import Blueprint, jsonify, request, current_app
from bookish.services.database import (
save_bookmark,
get_bookmarks,
delete_bookmark,
save_position,
get_position,
)
api_bp = Blueprint("api", __name__, url_prefix="/api")
# --- Bookmarks ---
@api_bp.route("/bookmarks/<content_hash>", methods=["GET"])
def api_get_bookmarks(content_hash):
bookmarks = get_bookmarks(content_hash)
return jsonify({"bookmarks": bookmarks})
@api_bp.route("/bookmarks", methods=["POST"])
def api_add_bookmark():
data = request.get_json(silent=True)
if not data or not data.get("content_hash") or not data.get("id"):
return jsonify({"error": "Richiesta non valida"}), 400
data["created"] = data.get("created", time.time())
save_bookmark(data)
return jsonify({"ok": True})
@api_bp.route("/bookmarks/<bookmark_id>", methods=["DELETE"])
def api_delete_bookmark(bookmark_id):
delete_bookmark(bookmark_id)
return jsonify({"ok": True})
# --- Reading positions ---
@api_bp.route("/position/<content_hash>", methods=["GET"])
def api_get_position(content_hash):
pos = get_position(content_hash)
if pos:
return jsonify({"position": pos})
return jsonify({"position": None})
@api_bp.route("/position/<content_hash>", methods=["PUT"])
def api_save_position(content_hash):
data = request.get_json(silent=True)
if not data:
return jsonify({"error": "Richiesta non valida"}), 400
data["type"] = data.get("type", "unknown")
save_position(content_hash, data)
return jsonify({"ok": True})