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