mirror of
https://github.com/koreader/koreader.git
synced 2025-08-10 00:52:38 +00:00
Optimize #11087 : 1. In `isReadyToExport`, check if the ip is set. If not, then the user cannot enable xmnote export. 2. Add author field in highlights.
171 lines
5.7 KiB
Lua
171 lines
5.7 KiB
Lua
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 "",
|
|
author = booknotes.author 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()
|
|
if self.settings.ip then return true end
|
|
return false
|
|
end
|
|
|
|
function XMNoteExporter:export(t)
|
|
if not self:isReadyToExport() then return false end
|
|
|
|
for _, booknotes in ipairs(t) do
|
|
local ok = self:createHighlights(booknotes)
|
|
if not ok then return false end
|
|
end
|
|
return true
|
|
end
|
|
|
|
return XMNoteExporter
|
|
|