From ff6ee697538a0a6007f1595552235c69339f1b5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=A4=8F=E9=B2=81=E8=B1=AB?= Date: Thu, 12 Oct 2023 20:54:31 +0800 Subject: [PATCH] Exporter: fix memos export, add flomo export (#10988) --- plugins/exporter.koplugin/main.lua | 7 +- plugins/exporter.koplugin/target/flomo.lua | 129 +++++++++++++++++++++ plugins/exporter.koplugin/target/memos.lua | 41 ++++++- 3 files changed, 170 insertions(+), 7 deletions(-) create mode 100644 plugins/exporter.koplugin/target/flomo.lua diff --git a/plugins/exporter.koplugin/main.lua b/plugins/exporter.koplugin/main.lua index bbbd59ede..c153e25cd 100644 --- a/plugins/exporter.koplugin/main.lua +++ b/plugins/exporter.koplugin/main.lua @@ -39,7 +39,7 @@ local _ = require("gettext") -- migrate settings from old "evernote.koplugin" or from previous (monolithic) "exporter.koplugin" local function migrateSettings() - local formats = { "html", "joplin", "json", "memos", "my_clippings", "readwise", "text" } + local formats = { "flomo", "html", "joplin", "json", "memos", "my_clippings", "readwise", "text" } local settings = G_reader_settings:readSetting("exporter") if not settings then @@ -98,14 +98,15 @@ end local Exporter = WidgetContainer:extend{ name = "exporter", targets = { + flomo = require("target/flomo"), html = require("target/html"), joplin = require("target/joplin"), json = require("target/json"), markdown = require("target/markdown"), - readwise = require("target/readwise"), - text = require("target/text"), memos = require("target/memos"), my_clippings = require("target/my_clippings"), + readwise = require("target/readwise"), + text = require("target/text"), }, } diff --git a/plugins/exporter.koplugin/target/flomo.lua b/plugins/exporter.koplugin/target/flomo.lua new file mode 100644 index 000000000..a27bd8ac1 --- /dev/null +++ b/plugins/exporter.koplugin/target/flomo.lua @@ -0,0 +1,129 @@ +local InputDialog = require("ui/widget/inputdialog") +local UIManager = require("ui/uimanager") +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 _ = require("gettext") + +-- readwise exporter +local FlomoExporter = require("base"):new { + name = "flomo", + is_remote = true, +} + +local function makeRequest(method, request_body, api) + 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 = api, + method = method, + sink = ltn12.sink.table(sink), + source = source, + headers = { + ["Content-Type"] = "application/json" + }, + } + local code, headers, status = socket.skip(1, http.request(request)) + socketutil:reset_timeout() + + if code ~= 200 then + logger.warn("Flomo: HTTP response code <> 200. Response status:", status or code or "network unreachable") + logger.dbg("Response headers:", headers) + return nil, status + end + + local response = json.decode(sink[1]) + return response +end + +function FlomoExporter:isReadyToExport() + if self.settings.api then return true end + return false +end + +function FlomoExporter:getMenuTable() + return { + text = _("Flomo"), + checked_func = function() return self:isEnabled() end, + sub_item_table = { + { + text = _("Set Flomo API URL"), + keep_menu_open = true, + callback = function() + local auth_dialog + auth_dialog = InputDialog:new { + title = _("Set API URL for Flomo"), + input = self.settings.api, + buttons = { + { + { + text = _("Cancel"), + id = "close", + callback = function() + UIManager:close(auth_dialog) + end + }, + { + text = _("Set API URL"), + callback = function() + self.settings.api = auth_dialog:getInputText() + self:saveSettings() + UIManager:close(auth_dialog) + end + } + } + } + } + UIManager:show(auth_dialog) + auth_dialog:onShowKeyboard() + end + }, + { + text = _("Export to Flomo"), + checked_func = function() return self:isEnabled() end, + callback = function() self:toggleEnabled() end, + }, + + } + } +end + +function FlomoExporter:createHighlights(booknotes) + local number = 0 + local error_number = 0 + for _, chapter in ipairs(booknotes) do + for _, clipping in ipairs(chapter) do + local highlight = clipping.text .. "\n\n" + if clipping.note then + highlight = highlight .. clipping.note .. "\n\n" + end + highlight = highlight .. booknotes.title .. " (page: " .. clipping.page .. ")\n\n #" .. booknotes.title .. " #koreader" + local result, err = makeRequest("POST", { content = highlight }, self.settings.api) + if not result then + logger.warn("error creating highlights", err) + error_number = error_number + 1 + end + number = number + 1 + end + end + local success_number = number - error_number + logger.dbg("createHighlights success number: " .. success_number .. " createHighlights error number: " .. error_number) + return true +end + +function FlomoExporter: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 FlomoExporter diff --git a/plugins/exporter.koplugin/target/memos.lua b/plugins/exporter.koplugin/target/memos.lua index d3c65ab93..afe12940b 100644 --- a/plugins/exporter.koplugin/target/memos.lua +++ b/plugins/exporter.koplugin/target/memos.lua @@ -14,7 +14,7 @@ local MemosExporter = require("base"):new { is_remote = true, } -local function makeRequest(method, request_body, api) +local function makeRequest(method, request_body, api, token) local sink = {} local request_body_json = json.encode(request_body) local source = ltn12.source.string(request_body_json) @@ -25,7 +25,8 @@ local function makeRequest(method, request_body, api) sink = ltn12.sink.table(sink), source = source, headers = { - ["Content-Type"] = "application/json" + ["Content-Type"] = "application/json", + ["Authorization"] = "Bearer " .. token }, } local code, headers, status = socket.skip(1, http.request(request)) @@ -42,7 +43,7 @@ local function makeRequest(method, request_body, api) end function MemosExporter:isReadyToExport() - if self.settings.api then return true end + if self.settings.api and self.settings.token then return true end return false end @@ -83,6 +84,38 @@ function MemosExporter:getMenuTable() auth_dialog:onShowKeyboard() end }, + { + text = _("Set Memos Token"), + keep_menu_open = true, + callback = function() + local token_dialog + token_dialog = InputDialog:new { + title = _("Set Token for Memos"), + input = self.settings.token, + buttons = { + { + { + text = _("Cancel"), + id = "close", + callback = function() + UIManager:close(token_dialog) + end + }, + { + text = _("Set Token"), + callback = function() + self.settings.token = token_dialog:getInputText() + self:saveSettings() + UIManager:close(token_dialog) + end + } + } + } + } + UIManager:show(token_dialog) + token_dialog:onShowKeyboard() + end + }, { text = _("Export to Memos"), checked_func = function() return self:isEnabled() end, @@ -103,7 +136,7 @@ function MemosExporter:createHighlights(booknotes) highlight = highlight .. clipping.note .. "\n\n" end highlight = highlight .. booknotes.title .. " (page: " .. clipping.page .. ")\n\n #" .. booknotes.title .. " #koreader" - local result, err = makeRequest("POST", { content = highlight }, self.settings.api) + local result, err = makeRequest("POST", { content = highlight }, self.settings.api, self.settings.token) if not result then logger.warn("error creating highlights", err) error_number = error_number + 1