Exporter: add XMNote export (#11087)

reviewable/pr11134/r1
WangKe 6 months ago committed by GitHub
parent 7870e83410
commit dea94026f1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -39,7 +39,7 @@ local _ = require("gettext")
-- migrate settings from old "evernote.koplugin" or from previous (monolithic) "exporter.koplugin"
local function migrateSettings()
local formats = { "flomo", "html", "joplin", "json", "memos", "my_clippings", "readwise", "text" }
local formats = { "flomo", "html", "joplin", "json", "memos", "my_clippings", "readwise", "text", "xmnote" }
local settings = G_reader_settings:readSetting("exporter")
if not settings then
@ -107,6 +107,7 @@ local Exporter = WidgetContainer:extend{
my_clippings = require("target/my_clippings"),
readwise = require("target/readwise"),
text = require("target/text"),
xmnote = require("target/xmnote"),
},
}

@ -0,0 +1,166 @@
local InputDialog = require("ui/widget/inputdialog")
local UIManager = require("ui/uimanager")
local InfoMessage = require("ui/widget/infomessage")
local BD = require("ui/bidi")
local DataStorage = require("datastorage")
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 util = require("ffi/util")
local T = util.template
local _ = require("gettext")
-- xmnote exporter
local XMNoteExporter = require("base"):new {
name = "xmnote",
is_remote = true,
server_port = 8080
}
function XMNoteExporter:getMenuTable()
return {
text = _("XMNote"),
checked_func = function() return self:isEnabled() end,
sub_item_table = {
{
text = _("Set XMNote IP"),
keep_menu_open = true,
callback = function()
local url_dialog
url_dialog = InputDialog:new {
title = _("Set XMNote IP"),
input = self.settings.ip,
buttons = {
{
{
text = _("Cancel"),
callback = function()
UIManager:close(url_dialog)
end
},
{
text = _("Set IP"),
callback = function()
local ip = url_dialog:getInputText()
self.settings.ip = ip
self:saveSettings()
UIManager:close(url_dialog)
end
}
}
}
}
UIManager:show(url_dialog)
url_dialog:onShowKeyboard()
end
} ,
{
text = _("Export to XMNote"),
checked_func = function() return self:isEnabled() end,
callback = function() self:toggleEnabled() end,
},
{
text = _("Help"),
keep_menu_open = true,
callback = function()
UIManager:show(InfoMessage:new {
text = T(_([[Before starting the export process, please make sure that your mobile and KOReader are connected to the same local network. Open XMNote and go to "My" - "Import Highlights" - "Import via API". At the bottom of the interface, you will find the IP address of your mobile device. Enter this IP address into KOReader to complete the configuration.]])
, BD.dirpath(DataStorage:getDataDir()))
})
end
}
}
}
end
function XMNoteExporter:createRequestBody(booknotes)
local book = {
title = booknotes.title or "",
type = 1,
locationUnit = 1,
}
local entries = {}
for _, chapter in ipairs(booknotes) do
for _, clipping in ipairs(chapter) do
local entry = {
text = clipping.text,
note = clipping.note or "",
chapter = clipping.chapter,
time = clipping.time
}
local page = tonumber(clipping.page)
if page ~= nil then
entry.page = page
end
table.insert(entries, entry)
end
end
book.entries = entries
return book
end
function XMNoteExporter: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 url = "http://".. self.settings.ip .. ":" .. self.server_port .. endpoint
local request = {
url = url,
method = method,
sink = ltn12.sink.table(sink),
source = source,
headers = {
["Content-Length"] = #request_body_json,
["Content-Type"] = "application/json"
},
}
local code, headers, status = socket.skip(1, http.request(request))
socketutil:reset_timeout()
if code ~= 200 then
logger.warn("XMNoteClient: HTTP response code <> 200. Response status: ", status)
logger.dbg("Response headers:", headers)
return nil, status
end
local response = json.decode(sink[1])
local api_code = response["code"]
if api_code ~= nil and api_code ~= 200 then
logger.warn("XMNoteClient: response code <> 200. message: ", response["message"])
logger.dbg("Response headers:", headers)
return nil, status
end
return response
end
function XMNoteExporter:createHighlights(booknotes)
local body = self:createRequestBody(booknotes)
local result, err = self:makeRequest("/send", "POST", body)
if not result then
logger.warn("error creating highlights", err)
return false
end
logger.dbg("createHighlights result", result)
return true
end
function XMNoteExporter:isReadyToExport()
return true
end
function XMNoteExporter:export(t)
for _, booknotes in ipairs(t) do
local ok = self:createHighlights(booknotes)
if not ok then return false end
end
return true
end
return XMNoteExporter
Loading…
Cancel
Save