forked from akai/readest
feat(kosync): use metadata hash to aggregate different versions of the same book (#2063)
This commit is contained in:
@@ -273,6 +273,69 @@ function ReadestSync:logout(menu)
|
||||
})
|
||||
end
|
||||
|
||||
function normalizeIdentifier(identifier)
|
||||
if identifier:match("urn:") then
|
||||
-- Slice after the last ':'
|
||||
return identifier:match("([^:]+)$")
|
||||
elseif identifier:match(":") then
|
||||
-- Slice after the first ':'
|
||||
return identifier:match("^[^:]+:(.+)$")
|
||||
end
|
||||
return identifier
|
||||
end
|
||||
|
||||
function normalizeAuthor(author)
|
||||
-- Trim leading and trailing whitespace
|
||||
author = author:gsub("^%s*(.-)%s*$", "%1")
|
||||
return author
|
||||
end
|
||||
|
||||
function ReadestSync:generateMetadataHash()
|
||||
local doc_props = self.ui.doc_settings:readSetting("doc_props") or {}
|
||||
local title = doc_props.title or ''
|
||||
if title == '' then
|
||||
local doc_path, filename = util.splitFilePathName(self.ui.doc_settings:readSetting("doc_path") or '')
|
||||
local basename, suffix = util.splitFileNameSuffix(filename)
|
||||
title = basename or ''
|
||||
end
|
||||
|
||||
local authors = doc_props.authors or ''
|
||||
if authors:find("\n") then
|
||||
authors = util.splitToArray(authors, "\n")
|
||||
for i, author in ipairs(authors) do
|
||||
authors[i] = normalizeAuthor(author)
|
||||
end
|
||||
authors = table.concat(authors, ",")
|
||||
else
|
||||
authors = normalizeAuthor(authors)
|
||||
end
|
||||
|
||||
local identifiers = doc_props.identifiers or ''
|
||||
if identifiers:find("\n") then
|
||||
identifiers = util.splitToArray(identifiers, "\n")
|
||||
for i, id in ipairs(identifiers) do
|
||||
identifiers[i] = normalizeIdentifier(id)
|
||||
end
|
||||
identifiers = table.concat(identifiers, ",")
|
||||
else
|
||||
identifiers = normalizeIdentifier(identifiers)
|
||||
end
|
||||
local doc_meta = title .. "|" .. authors .. "|" .. identifiers
|
||||
local meta_hash = sha2.md5(doc_meta)
|
||||
return meta_hash
|
||||
end
|
||||
|
||||
function ReadestSync:getMetaHash()
|
||||
local doc_readest_sync = self.ui.doc_settings:readSetting("readest_sync") or {}
|
||||
local meta_hash = doc_readest_sync.meta_hash
|
||||
if not meta_hash then
|
||||
meta_hash = self:generateMetadataHash()
|
||||
doc_readest_sync.meta_hash = meta_hash
|
||||
self.ui.doc_settings:saveSetting("readest_sync", doc_readest_sync)
|
||||
end
|
||||
return meta_hash
|
||||
end
|
||||
|
||||
function ReadestSync:getDocumentIdentifier()
|
||||
return self.ui.doc_settings:readSetting("partial_md5_checksum")
|
||||
end
|
||||
@@ -325,7 +388,8 @@ end
|
||||
|
||||
function ReadestSync:getCurrentBookConfig()
|
||||
local book_hash = self:getDocumentIdentifier()
|
||||
if not book_hash then
|
||||
local meta_hash = self:getMetaHash()
|
||||
if not book_hash or not meta_hash then
|
||||
UIManager:show(InfoMessage:new{
|
||||
text = _("Cannot identify the current book"),
|
||||
timeout = 2,
|
||||
@@ -335,6 +399,7 @@ function ReadestSync:getCurrentBookConfig()
|
||||
|
||||
local config = {
|
||||
bookHash = book_hash,
|
||||
metaHash = meta_hash,
|
||||
progress = "",
|
||||
xpointer = "",
|
||||
updatedAt = os.time() * 1000,
|
||||
@@ -437,7 +502,8 @@ function ReadestSync:pullBookConfig(interactive)
|
||||
end
|
||||
|
||||
local book_hash = self:getDocumentIdentifier()
|
||||
if not book_hash then return end
|
||||
local meta_hash = self:getMetaHash()
|
||||
if not book_hash or not meta_hash then return end
|
||||
|
||||
if NetworkMgr:willRerunWhenOnline(function() self:pullBookConfig(interactive) end) then
|
||||
return
|
||||
@@ -468,6 +534,7 @@ function ReadestSync:pullBookConfig(interactive)
|
||||
since = 0,
|
||||
type = "configs",
|
||||
book = book_hash,
|
||||
meta_hash = meta_hash,
|
||||
},
|
||||
function(success, response)
|
||||
if not success then
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
{
|
||||
"base_url": "https://web.readest.com/api",
|
||||
"name": "readest-sync-api",
|
||||
"methods": {
|
||||
"pullChanges": {
|
||||
"path": "/sync",
|
||||
"method": "GET",
|
||||
"required_params": ["since", "type", "book"],
|
||||
"expected_status": [200, 400, 301, 401, 403]
|
||||
},
|
||||
"pushChanges": {
|
||||
"path": "/sync",
|
||||
"method": "POST",
|
||||
"required_params": ["books", "notes", "configs"],
|
||||
"payload": ["books", "notes", "configs"],
|
||||
"expected_status": [200, 201, 301, 400, 401, 403]
|
||||
}
|
||||
"base_url": "https://web.readest.com/api",
|
||||
"name": "readest-sync-api",
|
||||
"methods": {
|
||||
"pullChanges": {
|
||||
"path": "/sync",
|
||||
"method": "GET",
|
||||
"required_params": ["since", "type", "book", "meta_hash"],
|
||||
"expected_status": [200, 400, 301, 401, 403]
|
||||
},
|
||||
"pushChanges": {
|
||||
"path": "/sync",
|
||||
"method": "POST",
|
||||
"required_params": ["books", "notes", "configs"],
|
||||
"payload": ["books", "notes", "configs"],
|
||||
"expected_status": [200, 201, 301, 400, 401, 403]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,6 +81,7 @@ function ReadestSyncClient:pullChanges(params, callback)
|
||||
since = params.since,
|
||||
type = params.type,
|
||||
book = params.book,
|
||||
meta_hash = params.meta_hash,
|
||||
})
|
||||
end)
|
||||
if ok then
|
||||
|
||||
@@ -1,33 +1,33 @@
|
||||
{
|
||||
"base_url": "https://readest.supabase.co/auth/v1/",
|
||||
"name": "supabase-auth-api",
|
||||
"methods": {
|
||||
"sign_in_password": {
|
||||
"path": "/token?grant_type=password",
|
||||
"method": "POST",
|
||||
"required_params": ["email", "password"],
|
||||
"payload": ["email", "password"],
|
||||
"expected_status": [200, 400, 401]
|
||||
},
|
||||
"refresh_token": {
|
||||
"path": "/token?grant_type=refresh_token",
|
||||
"method": "POST",
|
||||
"required_params": ["refresh_token"],
|
||||
"payload": ["refresh_token"],
|
||||
"expected_status": [200, 400, 401, 403]
|
||||
},
|
||||
"sign_out": {
|
||||
"path": "/logout",
|
||||
"method": "POST",
|
||||
"required_params": [],
|
||||
"payload": [],
|
||||
"expected_status": [204, 401]
|
||||
},
|
||||
"get_user": {
|
||||
"path": "/user",
|
||||
"method": "GET",
|
||||
"required_params": [],
|
||||
"expected_status": [200, 401]
|
||||
}
|
||||
"base_url": "https://readest.supabase.co/auth/v1/",
|
||||
"name": "supabase-auth-api",
|
||||
"methods": {
|
||||
"sign_in_password": {
|
||||
"path": "/token?grant_type=password",
|
||||
"method": "POST",
|
||||
"required_params": ["email", "password"],
|
||||
"payload": ["email", "password"],
|
||||
"expected_status": [200, 400, 401]
|
||||
},
|
||||
"refresh_token": {
|
||||
"path": "/token?grant_type=refresh_token",
|
||||
"method": "POST",
|
||||
"required_params": ["refresh_token"],
|
||||
"payload": ["refresh_token"],
|
||||
"expected_status": [200, 400, 401, 403]
|
||||
},
|
||||
"sign_out": {
|
||||
"path": "/logout",
|
||||
"method": "POST",
|
||||
"required_params": [],
|
||||
"payload": [],
|
||||
"expected_status": [204, 401]
|
||||
},
|
||||
"get_user": {
|
||||
"path": "/user",
|
||||
"method": "GET",
|
||||
"required_params": [],
|
||||
"expected_status": [200, 401]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user