mirror of
https://github.com/koreader/koreader.git
synced 2025-08-10 00:52:38 +00:00
[plugin] Exporter: add Readwise.io support (#8548)
This extends exporter.koplugin with support for [Readwise.io](https://readwise.io), a highlight/notes aggregation service. [Readwise API documentation](https://readwise.io/api_deets) This additionally improves the highlight exporter's ability to get the correct title and author of a document, by checking actual metadata instead of inferring from filename. It also includes a modification to the plugin's highlight parsing logic to separate the highlight contents in `.text` from the notes in `.note`. This change actually fixes an existing bug in the HTML export template note.tpl, which has been missing notes because of the lack of the `.note` field.
This commit is contained in:
70
plugins/exporter.koplugin/ReadwiseClient.lua
Normal file
70
plugins/exporter.koplugin/ReadwiseClient.lua
Normal file
@@ -0,0 +1,70 @@
|
||||
local http = require("socket.http")
|
||||
local json = require("json")
|
||||
local logger = require("logger")
|
||||
local ltn12 = require("ltn12")
|
||||
local socket = require("socket")
|
||||
local socketutil = require("socketutil")
|
||||
|
||||
local ReadwiseClient = {
|
||||
auth_token = ""
|
||||
}
|
||||
|
||||
function ReadwiseClient:new(o)
|
||||
o = o or {}
|
||||
self.__index = self
|
||||
setmetatable(o, self)
|
||||
return o
|
||||
end
|
||||
|
||||
function ReadwiseClient:_makeRequest(endpoint, method, request_body)
|
||||
local sink = {}
|
||||
local request_body_json = json.encode(request_body)
|
||||
local source = ltn12.source.string(request_body_json)
|
||||
socketutil:set_timeout(socketutil.LARGE_BLOCK_TIMEOUT, socketutil.LARGE_TOTAL_TIMEOUT)
|
||||
local request = {
|
||||
url = "https://readwise.io/api/v2/" .. endpoint,
|
||||
method = method,
|
||||
sink = ltn12.sink.table(sink),
|
||||
source = source,
|
||||
headers = {
|
||||
["Content-Length"] = #request_body_json,
|
||||
["Content-Type"] = "application/json",
|
||||
["Authorization"] = "Token " .. self.auth_token
|
||||
},
|
||||
}
|
||||
local code, _, status = socket.skip(1, http.request(request))
|
||||
socketutil:reset_timeout()
|
||||
|
||||
if code ~= 200 then
|
||||
logger.warn("ReadwiseClient: HTTP response code <> 200. Response status: ", status)
|
||||
error("ReadwiseClient: HTTP response code <> 200.")
|
||||
end
|
||||
|
||||
local response = json.decode(sink[1])
|
||||
|
||||
return response
|
||||
end
|
||||
|
||||
function ReadwiseClient:createHighlights(booknotes)
|
||||
local highlights = {}
|
||||
for _, chapter in ipairs(booknotes) do
|
||||
for _, clipping in ipairs(chapter) do
|
||||
local highlight = {
|
||||
text = clipping.text,
|
||||
title = booknotes.title,
|
||||
author = booknotes.author ~= "" and booknotes.author or nil, -- optional author
|
||||
source_type = "koreader",
|
||||
category = "books",
|
||||
note = clipping.note,
|
||||
location = clipping.page,
|
||||
location_type = "page",
|
||||
highlighted_at = os.date("!%Y-%m-%dT%TZ", clipping.time),
|
||||
}
|
||||
table.insert(highlights, highlight)
|
||||
end
|
||||
end
|
||||
local result = self:_makeRequest("highlights", "POST", { highlights = highlights })
|
||||
logger.dbg("ReadwiseClient createHighlights result", result)
|
||||
end
|
||||
|
||||
return ReadwiseClient
|
||||
Reference in New Issue
Block a user