2
0
mirror of https://github.com/koreader/koreader synced 2024-11-04 12:00:25 +00:00
koreader/plugins/evernote.koplugin/main.lua
Hans-Werner Hilse 3066c86e38 Refactoring hardware abstraction
This is a major overhaul of the hardware abstraction layer.
A few notes:

General platform distinction happens in
  frontend/device.lua
which will delegate everything else to
  frontend/device/<platform_name>/device.lua
which should extend
  frontend/device/generic/device.lua

Screen handling is implemented in
  frontend/device/screen.lua
which includes the *functionality* to support device specifics.
Actually setting up the device specific functionality, however,
is done in the device specific setup code in the relevant
device.lua file.

The same goes for input handling.
2014-11-02 21:19:04 +01:00

404 lines
14 KiB
Lua

local InputContainer = require("ui/widget/container/inputcontainer")
local LoginDialog = require("ui/widget/logindialog")
local InfoMessage = require("ui/widget/infomessage")
local DocSettings = require("docsettings")
local NetworkMgr = require("ui/networkmgr")
local UIManager = require("ui/uimanager")
local Screen = require("device").screen
local Event = require("ui/event")
local DEBUG = require("dbg")
local _ = require("gettext")
local slt2 = require('slt2')
local MyClipping = require("clip")
local EvernoteExporter = InputContainer:new{
name = "evernote",
login_title = _("Login to Evernote"),
notebook_name = _("Koreader Notes"),
evernote_domain = nil,
notemarks = _("Note: "),
clipping_dir = "./clipboard",
evernote_token,
notebook_guid,
}
function EvernoteExporter:init()
self.ui.menu:registerToMainMenu(self)
local settings = G_reader_settings:readSetting("evernote") or {}
self.evernote_domain = settings.domain
self.evernote_username = settings.username or ""
self.evernote_token = settings.token
self.notebook_guid = settings.notebook
self.html_export = settings.html_export or false
self.parser = MyClipping:new{
my_clippings = "/mnt/us/documents/My Clippings.txt",
history_dir = "./history",
}
self.template = slt2.loadfile(self.path.."/note.tpl")
self.config = DocSettings:open(self.path)
end
function EvernoteExporter:addToMainMenu(tab_item_table)
table.insert(tab_item_table.plugins, {
text = _("Evernote"),
sub_item_table = {
{
text_func = function()
local domain = nil
if self.evernote_domain == "sandbox" then
domain = "Sandbox"
elseif self.evernote_domain == "yinxiang" then
domain = "Yinxiang"
else
domain = "Evernote"
end
return self.evernote_token and (_("Logout") .. " " .. domain)
or _("Login")
end,
callback_func = function()
return self.evernote_token and function() self:logout() end
or nil
end,
sub_item_table_func = function()
return not self.evernote_token and {
{
text = "Evernote",
callback = function()
self.evernote_domain = nil
self:login()
end
},
{
text = "印象笔记",
callback = function()
self.evernote_domain = "yinxiang"
self:login()
end
}
} or nil
end,
},
{
text = _("Export all notes in this book"),
enabled_func = function()
return self.evernote_token ~= nil or self.html_export ~= false
end,
callback = function()
UIManager:scheduleIn(0.5, function()
self:exportCurrentNotes(self.view)
end)
UIManager:show(InfoMessage:new{
text = _("Exporting may take several seconds..."),
timeout = 1,
})
end
},
{
text = _("Export all notes in your library"),
enabled_func = function()
return self.evernote_token ~= nil or self.html_export ~= false
end,
callback = function()
UIManager:scheduleIn(0.5, function()
self:exportAllNotes()
end)
UIManager:show(InfoMessage:new{
text = _("Exporting may take several minutes..."),
timeout = 1,
})
end
},
{
text = _("Export to local HTML files"),
checked_func = function() return self.html_export end,
callback = function()
self.html_export = not self.html_export
end
},
}
})
end
function EvernoteExporter:login()
self.login_dialog = LoginDialog:new{
title = self.login_title,
username = self.evernote_username or "",
buttons = {
{
{
text = _("Cancel"),
enabled = true,
callback = function()
self:closeDialog()
end,
},
{
text = _("Login"),
enabled = true,
callback = function()
local username, password = self:getCredential()
self:closeDialog()
UIManager:scheduleIn(0.5, function()
self:doLogin(username, password)
end)
UIManager:show(InfoMessage:new{
text = _("Logging in please wait..."),
timeout = 1,
})
end,
},
},
},
width = Screen:getWidth() * 0.8,
height = Screen:getHeight() * 0.4,
}
self.login_dialog:onShowKeyboard()
UIManager:show(self.login_dialog)
end
function EvernoteExporter:closeDialog()
self.login_dialog:onClose()
UIManager:close(self.login_dialog)
end
function EvernoteExporter:getCredential()
return self.login_dialog:getCredential()
end
function EvernoteExporter:doLogin(username, password)
local EvernoteOAuth = require("EvernoteOAuth")
local EvernoteClient = require("EvernoteClient")
local oauth = EvernoteOAuth:new{
domain = self.evernote_domain,
username = username,
password = password,
}
self.evernote_username = username
local ok, token = pcall(oauth.getToken, oauth)
-- prompt users to turn on Wifi if network is unreachable
if not ok and token and token:find("Network is unreachable") then
NetworkMgr:promptWifiOn()
return
elseif not ok and token then
UIManager:show(InfoMessage:new{
text = _("Error occurs when login:") .. "\n" .. token,
})
return
end
local client = EvernoteClient:new{
domain = self.evernote_domain,
authToken = token,
}
local ok, guid = pcall(self.getExportNotebook, self, client)
if not ok and guid and guid:find("Transport not open") then
NetworkMgr:promptWifiOn()
return
elseif not ok and guid then
UIManager:show(InfoMessage:new{
text = _("Error occurs when login:") .. "\n" .. guid,
})
elseif ok and guid then
self.evernote_token = token
self.notebook_guid = guid
UIManager:show(InfoMessage:new{
text = _("Login to Evernote successfully"),
})
end
self:onSaveSettings()
end
function EvernoteExporter:logout()
self.evernote_token = nil
self.notebook_guid = nil
self.evernote_domain = nil
self:onSaveSettings()
end
function EvernoteExporter:onSaveSettings()
local settings = {
domain = self.evernote_domain,
username = self.evernote_username,
token = self.evernote_token,
notebook = self.notebook_guid,
html_export = self.html_export,
}
G_reader_settings:saveSetting("evernote", settings)
end
function EvernoteExporter:getExportNotebook(client)
local name = self.notebook_name
return client:findNotebookByTitle(name) or client:createNotebook(name).guid
end
function EvernoteExporter:exportCurrentNotes(view)
local clippings = self.parser:parseCurrentDoc(view)
self:exportClippings(clippings)
end
function EvernoteExporter:updateHistoryClippings(clippings, new_clippings)
-- update clippings from history clippings
for title, booknotes in pairs(new_clippings) do
for chapter_index, chapternotes in ipairs(booknotes) do
for note_index, note in ipairs(chapternotes) do
if clippings[title] == nil or clippings[title][chapter_index] == nil
or clippings[title][chapter_index][note_index] == nil
or clippings[title][chapter_index][note_index].page ~= note.page
or clippings[title][chapter_index][note_index].time ~= note.time
or clippings[title][chapter_index][note_index].text ~= note.text
or clippings[title][chapter_index][note_index].note ~= note.note then
DEBUG("found new notes in history", booknotes.title)
clippings[title] = booknotes
end
end
end
end
return clippings
end
function EvernoteExporter:updateMyClippings(clippings, new_clippings)
-- only new titles or new notes in My clippings are updated to clippings
-- since appending is the only way to modify notes in My Clippings
for title, booknotes in pairs(new_clippings) do
if clippings[title] == nil or #clippings[title] < #booknotes then
DEBUG("found new notes in MyClipping", booknotes.title)
clippings[title] = booknotes
end
end
return clippings
end
function EvernoteExporter:exportAllNotes()
local clippings = self.config:readSetting("clippings") or {}
clippings = self:updateHistoryClippings(clippings, self.parser:parseHistory())
clippings = self:updateMyClippings(clippings, self.parser:parseMyClippings())
-- remove blank entries
for title, booknotes in pairs(clippings) do
-- chapter number is zero
if #booknotes == 0 then
clippings[title] = nil
end
end
--DEBUG("clippings", clippings)
self:exportClippings(clippings)
self.config:saveSetting("clippings", clippings)
self.config:flush()
end
function EvernoteExporter:exportClippings(clippings)
local client = nil
local exported_stamp = "html"
if not self.html_export then
client = require("EvernoteClient"):new{
domain = self.evernote_domain,
authToken = self.evernote_token,
}
exported_stamp = self.notebook_guid
end
local export_count, error_count = 0, 0
local export_title, error_title
for title, booknotes in pairs(clippings) do
if type(booknotes.exported) ~= "table" then
booknotes.exported = {}
end
-- check if booknotes are exported in this notebook
-- so that booknotes will still be exported after switching user account
if booknotes.exported[exported_stamp] ~= true then
local ok, err
if self.html_export then
ok, err = pcall(self.exportBooknotesToHTML, self,
title, booknotes)
else
ok, err = pcall(self.exportBooknotesToEvernote, self,
client, title, booknotes)
end
-- error reporting
if not ok and err and err:find("Transport not open") then
NetworkMgr:promptWifiOn()
return
elseif not ok and err then
DEBUG("Error occurs when exporting book:", title, err)
error_count = error_count + 1
error_title = title
elseif ok then
DEBUG("Exported notes in book:", title)
export_count = export_count + 1
export_title = title
booknotes.exported[exported_stamp] = true
end
end
end
local msg = "Not exported anything."
local all_count = export_count + error_count
if export_count > 0 and error_count == 0 then
if all_count == 1 then
msg = _("Exported notes in book:") .. "\n" .. export_title
else
msg = _("Exported notes in book:") .. "\n" .. export_title
msg = msg .. "\n" .. _("and ") .. all_count-1 .. _(" others.")
end
elseif error_count > 0 then
if all_count == 1 then
msg = _("Error occurs when exporting book:") .. "\n" .. error_title
else
msg = _("Errors occur when exporting book:") .. "\n" .. error_title
msg = msg .. "\n" .. _("and ") .. error_count-1 .. (" others.")
end
end
UIManager:show(InfoMessage:new{ text = msg })
end
function EvernoteExporter:exportBooknotesToEvernote(client, title, booknotes)
local content = slt2.render(self.template, {
booknotes = booknotes,
notemarks = self.notemarks,
})
--DEBUG("content", content)
local note_guid = client:findNoteByTitle(title, self.notebook_guid)
local resources = {}
for _, chapter in ipairs(booknotes) do
for _, clipping in ipairs(chapter) do
if clipping.image then
table.insert(resources, {
image = clipping.image
})
-- nullify clipping image after passing it to evernote client
clipping.image = nil
end
end
end
if not note_guid then
client:createNote(title, content, resources, {}, self.notebook_guid)
else
client:updateNote(note_guid, title, content, resources, {}, self.notebook_guid)
end
end
function EvernoteExporter:exportBooknotesToHTML(title, booknotes)
local content = slt2.render(self.template, {
booknotes = booknotes,
notemarks = self.notemarks,
})
--DEBUG("content", content)
local html = io.open(self.clipping_dir .. "/" .. title .. ".html", "w")
if html then
html:write(content)
html:close()
end
end
return EvernoteExporter