feat: Add kosync user registration and switch to crosspoint-sync server (#2587)

Implements createUser() endpoint to allow account creation via the
KOSync protocol. Changes default sync server from sync.koreader.rocks to
sync.crosspointreader.com with migration logic to preserve existing
users' server settings. Extends sync protocol to include position data
(spine index, page numbers, xpath) that crosspoint-sync supports while
remaining compatible with standard kosync servers.
This commit is contained in:
Justin Mitchell
2026-07-18 14:50:51 -04:00
committed by GitHub
parent 9737cb335c
commit b1d037569b
11 changed files with 320 additions and 53 deletions
+42 -8
View File
@@ -14,17 +14,33 @@ struct KOReaderMetadata {
std::string authors; // Author(s) from EPUB metadata
};
/**
* Rich CrossPoint position sent alongside progress uploads. Maps 1:1 onto the
* crosspoint-sync extended `position` object (see crosspoint-sync docs/API.md).
* The official KOSync server ignores unknown fields; crosspoint-sync stores it
* so CrossPoint<->CrossPoint sync is lossless instead of xpath-approximated.
*/
struct KOReaderRichPosition {
uint32_t pctQ = 0; // Percentage quantized 0..1,000,000 (authoritative)
uint16_t spineIndex = 0; // Spine (chapter) index
uint16_t pageNumber = 0; // Page within spine (layout-dependent hint)
uint16_t totalPages = 1; // Spine page count (layout-dependent hint)
std::optional<uint16_t> paragraphIndex; // Synthetic 1-based paragraph index
std::string xpath; // KOReader-style xpath (server cap: 120 bytes)
};
/**
* Progress data from KOReader sync server.
*/
struct KOReaderProgress {
std::string document; // Document hash
std::string progress; // XPath-like progress string
float percentage; // Progress percentage (0.0 to 1.0)
std::string device; // Device name
std::string deviceId; // Device ID
int64_t timestamp; // Unix timestamp of last update
std::optional<KOReaderMetadata> metadata; // Optional document metadata
std::string document; // Document hash
std::string progress; // XPath-like progress string
float percentage; // Progress percentage (0.0 to 1.0)
std::string device; // Device name
std::string deviceId; // Device ID
int64_t timestamp; // Unix timestamp of last update
std::optional<KOReaderMetadata> metadata; // Optional document metadata
std::optional<KOReaderRichPosition> position; // Optional rich position (crosspoint-sync servers only)
};
/**
@@ -43,7 +59,17 @@ struct KOReaderProgress {
*/
class KOReaderSyncClient {
public:
enum Error { OK = 0, NO_CREDENTIALS, NETWORK_ERROR, AUTH_FAILED, SERVER_ERROR, JSON_ERROR, NOT_FOUND, LOW_MEMORY };
enum Error {
OK = 0,
NO_CREDENTIALS,
NETWORK_ERROR,
AUTH_FAILED,
SERVER_ERROR,
JSON_ERROR,
NOT_FOUND,
LOW_MEMORY,
USER_EXISTS
};
/**
* Authenticate with the sync server (validate credentials).
@@ -51,6 +77,14 @@ class KOReaderSyncClient {
*/
static Error authenticate();
/**
* Register a new account on the sync server using the stored credentials
* (POST /users/create with the MD5 auth key — the server never sees the
* plain password).
* @return OK on success, USER_EXISTS if the username is taken
*/
static Error createUser();
/**
* Get reading progress for a document.
* @param documentHash The document hash (from KOReaderDocumentId)