mirror of https://github.com/koreader/koreader
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
351 lines
12 KiB
Lua
351 lines
12 KiB
Lua
--[[--
|
|
Download URLs as EPUBs
|
|
|
|
@module koplugin.DownloadToEPUB
|
|
--]]--
|
|
local BD = require("ui/bidi")
|
|
local Blitbuffer = require("ffi/blitbuffer")
|
|
local ConfirmBox = require("ui/widget/confirmbox")
|
|
local DataStorage = require("datastorage")
|
|
local Device = require("device")
|
|
local Dispatcher = require("dispatcher")
|
|
local Event = require("ui/event")
|
|
local FFIUtil = require("ffi/util")
|
|
local FileManager = require("apps/filemanager/filemanager")
|
|
local InfoMessage = require("ui/widget/infomessage")
|
|
local LuaSettings = require("frontend/luasettings")
|
|
local MultiConfirmBox = require("ui/widget/multiconfirmbox")
|
|
local NetworkMgr = require("ui/network/manager")
|
|
local UIManager = require("ui/uimanager")
|
|
local WidgetContainer = require("ui/widget/container/widgetcontainer")
|
|
local VerticalGroup = require("ui/widget/verticalgroup")
|
|
local Screen = Device.screen
|
|
local Size = require("ui/size")
|
|
local filemanagerutil = require("apps/filemanager/filemanagerutil")
|
|
local logger = require("logger")
|
|
local util = require("frontend/util")
|
|
local T = FFIUtil.template
|
|
local _ = require("gettext")
|
|
-- Gazette Modules
|
|
local EpubBuildDirector = require("libs/gazette/epubbuilddirector")
|
|
local WebPage = require("libs/gazette/resources/webpage")
|
|
local ResourceAdapter = require("libs/gazette/resources/webpageadapter")
|
|
local Epub = require("libs/gazette/epub/epub")
|
|
local History = require("epubhistory")
|
|
local HistoryView = require("epubhistoryview")
|
|
|
|
local DownloadToEpub = WidgetContainer:new{
|
|
name = "Download to EPUB",
|
|
download_directory = ("%s/%s/"):format(DataStorage:getFullDataDir(), "EPUB Downloads")
|
|
}
|
|
|
|
local EpubBuilder = {
|
|
output_directory = nil,
|
|
}
|
|
|
|
function DownloadToEpub:init()
|
|
self.settings = self.readSettings()
|
|
if self.settings.data.download_directory then
|
|
self.download_directory = self.settings.data.download_directory
|
|
end
|
|
self:createDownloadDirectoryIfNotExists()
|
|
self.ui.menu:registerToMainMenu(self)
|
|
if self.ui and self.ui.link then
|
|
self.ui.link:addToExternalLinkDialog("30_downloadtoepub", function(this, link_url)
|
|
return {
|
|
text = _("Download to EPUB"),
|
|
callback = function()
|
|
UIManager:close(this.external_link_dialog)
|
|
this.ui:handleEvent(Event:new("DownloadEpubFromUrl", link_url))
|
|
end,
|
|
show_in_dialog_func = function()
|
|
return true
|
|
end
|
|
}
|
|
end)
|
|
end
|
|
end
|
|
|
|
function DownloadToEpub:addToMainMenu(menu_items)
|
|
menu_items.downloadtoepub = {
|
|
text = _("Download to EPUB"),
|
|
sorting_hint = "tools",
|
|
sub_item_table = {
|
|
{
|
|
text = _("Go to EPUB downloads"),
|
|
callback = function()
|
|
self:goToDownloadDirectory()
|
|
end,
|
|
},
|
|
{
|
|
text = _("Settings"),
|
|
sub_item_table = {
|
|
{
|
|
text_func = function()
|
|
local path = filemanagerutil.abbreviate(self.download_directory)
|
|
return T(_("Set download directory (%1)"), BD.dirpath(path))
|
|
end,
|
|
keep_menu_open = true,
|
|
callback = function() self:setDownloadDirectory() end,
|
|
},
|
|
}
|
|
},
|
|
{
|
|
text = _("About"),
|
|
keep_menu_open = true,
|
|
callback = function()
|
|
UIManager:show(InfoMessage:new{
|
|
text = "DownloadToEpub lets you download external links as EPUBs to your device."
|
|
})
|
|
end,
|
|
},
|
|
}
|
|
}
|
|
local history_view = HistoryView:new{}
|
|
local last_download_item = history_view:getLastDownloadButton(function(history_item)
|
|
self:maybeOpenEpub(history_item['download_path'])
|
|
end)
|
|
local history_menu_items = history_view:getMenuItems(function(history_item)
|
|
self:maybeOpenEpub(history_item['download_path'])
|
|
end)
|
|
if last_download_item then table.insert(menu_items.downloadtoepub.sub_item_table, 2, last_download_item) end
|
|
if history_menu_items then table.insert(menu_items.downloadtoepub.sub_item_table, 3, history_menu_items[1]) end
|
|
end
|
|
|
|
function DownloadToEpub:maybeOpenEpub(file_path)
|
|
if util.pathExists(file_path) then
|
|
logger.dbg("DownloadToEpub: Opening " .. file_path)
|
|
local Event = require("ui/event")
|
|
UIManager:broadcastEvent(Event:new("SetupShowReader"))
|
|
local ReaderUI = require("apps/reader/readerui")
|
|
ReaderUI:showReader(file_path)
|
|
else
|
|
logger.dbg("DownloadToEpub: Couldn't open " .. file_path .. ". It's been moved or deleted.")
|
|
self:showRedownloadPrompt(file_path)
|
|
end
|
|
end
|
|
|
|
function DownloadToEpub:readSettings()
|
|
local settings = LuaSettings:open(DataStorage:getSettingsDir() .. "downloadtoepub.lua")
|
|
if not settings.data.downloadtoepub then
|
|
settings.data.downloadtoepub = {}
|
|
end
|
|
return settings
|
|
end
|
|
|
|
function DownloadToEpub:saveSettings()
|
|
local temp_settings = {
|
|
download_directory = self.download_directory
|
|
}
|
|
self.settings:saveSetting("downloadtoepub", temp_settings)
|
|
self.settings:flush()
|
|
end
|
|
|
|
function DownloadToEpub:setDownloadDirectory()
|
|
local downloadmgr = require("ui/downloadmgr")
|
|
downloadmgr:new{
|
|
onConfirm = function(path)
|
|
self.download_directory = path
|
|
self:saveSettings()
|
|
end
|
|
}:chooseDir()
|
|
end
|
|
|
|
function DownloadToEpub:goToDownloadDirectory()
|
|
local FileManager = require("apps/filemanager/filemanager")
|
|
if self.ui.document then
|
|
self.ui:onClose()
|
|
end
|
|
if FileManager.instance then
|
|
FileManager.instance:reinit(self.download_directory)
|
|
else
|
|
FileManager:showFiles(self.download_directory)
|
|
end
|
|
end
|
|
|
|
function DownloadToEpub:createDownloadDirectoryIfNotExists()
|
|
if not util.pathExists(self.download_directory) then
|
|
logger.dbg("DownloadToEpub: Creating path (" .. self.download_directory .. ")")
|
|
lfs.mkdir(self.download_directory)
|
|
end
|
|
end
|
|
|
|
function DownloadToEpub:onDownloadEpubFromUrl(link_url)
|
|
local prompt
|
|
prompt = ConfirmBox:new{
|
|
text = T(_("Download to EPUB? \n\nLink: %1"), link_url),
|
|
ok_text = _("Yes"),
|
|
ok_callback = function()
|
|
UIManager:close(prompt)
|
|
self:downloadEpubWithUi(link_url, function(file_path, err)
|
|
if err then
|
|
UIManager:show(InfoMessage:new{ text = T(_("Error downloading EPUB: %1", err)) })
|
|
else
|
|
local history = History:new{}
|
|
history:init()
|
|
logger.dbg("DownloadToEpub: Maybe deleting from history " .. link_url)
|
|
history:remove(link_url) -- link might have already been downloaded. If so, remove the history item.
|
|
logger.dbg("DownloadToEpub: Adding to history " .. link_url .. " " .. file_path)
|
|
history:add(link_url, file_path)
|
|
logger.dbg("DownloadToEpub: Finished downloading epub to " .. file_path)
|
|
self:showReadPrompt(file_path)
|
|
end
|
|
end)
|
|
end,
|
|
}
|
|
UIManager:show(prompt)
|
|
end
|
|
|
|
function DownloadToEpub:downloadEpubWithUi(link_url, callback)
|
|
local info = InfoMessage:new{ text = ("Downloading... " .. link_url) }
|
|
UIManager:show(info)
|
|
UIManager:forceRePaint()
|
|
UIManager:close(info)
|
|
|
|
NetworkMgr:runWhenOnline(function()
|
|
local epub_builder = EpubBuilder:new{
|
|
output_directory = self.download_directory,
|
|
}
|
|
local file_path, err = epub_builder:buildFromUrl(link_url)
|
|
callback(file_path, err)
|
|
end)
|
|
end
|
|
|
|
function DownloadToEpub:showRedownloadPrompt(file_path) -- supply this with a directory?
|
|
local prompt
|
|
|
|
local history = History:new{}
|
|
history:init()
|
|
local history_item = history:find(file_path)
|
|
|
|
if history_item then
|
|
prompt = MultiConfirmBox:new{
|
|
text = T(_("Couldn't open EPUB! \n\nFile has been moved since download (%1)\n\nInitially downloaded from (%2)\n\nWhat would you like to do?"),
|
|
file_path,
|
|
history_item.url),
|
|
choice1_text = _("Redownload EPUB"),
|
|
choice1_callback = function()
|
|
logger.dbg("DownloadToEpub: Redownloading " .. history_item.url)
|
|
UIManager:close(prompt)
|
|
self:onDownloadEpubFromUrl(history_item.url)
|
|
end,
|
|
choice2_text = _("Delete from history"),
|
|
choice2_callback = function()
|
|
logger.dbg("DownloadToEpub: Deleting from history " .. history_item.url)
|
|
history:remove(history_item.url)
|
|
UIManager:close(prompt)
|
|
end,
|
|
}
|
|
else
|
|
prompt = InfoMessage:new{
|
|
text = _("Couldn't open EPUB! EPUB has been deleted or moved since being downloaded."),
|
|
show_icon = false,
|
|
timeout = 10,
|
|
}
|
|
end
|
|
UIManager:show(prompt)
|
|
end
|
|
|
|
function DownloadToEpub:showReadPrompt(file_path)
|
|
local prompt = ConfirmBox:new{
|
|
text = _("EPUB downloaded. Would you like to read it now?"),
|
|
ok_text = _("Open EPUB"),
|
|
ok_callback = function()
|
|
logger.dbg("DownloadToEpub: Opening " .. file_path)
|
|
local Event = require("ui/event")
|
|
UIManager:broadcastEvent(Event:new("SetupShowReader"))
|
|
UIManager:close(prompt)
|
|
local ReaderUI = require("apps/reader/readerui")
|
|
ReaderUI:showReader(file_path)
|
|
end,
|
|
}
|
|
UIManager:show(prompt)
|
|
end
|
|
|
|
function EpubBuilder:new(o)
|
|
o = o or {}
|
|
setmetatable(o, self)
|
|
self.__index = self
|
|
|
|
return o
|
|
end
|
|
|
|
function EpubBuilder:buildFromUrl(url)
|
|
logger.dbg("DownloadToEpub: Begin download of " .. url .. " outputting to " .. self.output_directory)
|
|
|
|
local info = InfoMessage:new{ text = _("Getting webpage…") }
|
|
UIManager:show(info)
|
|
UIManager:forceRePaint()
|
|
UIManager:close(info)
|
|
|
|
local webpage, err = self:createWebpage(url)
|
|
|
|
if not webpage then
|
|
logger.dbg("DownloadToEpub: " .. err)
|
|
return false, err
|
|
end
|
|
|
|
info = InfoMessage:new{ text = _("Building EPUB…") }
|
|
UIManager:show(info)
|
|
UIManager:forceRePaint()
|
|
UIManager:close(info)
|
|
|
|
local epub = Epub:new{}
|
|
epub:addFromList(ResourceAdapter:new(webpage))
|
|
epub:setTitle(webpage.title)
|
|
epub:setAuthor("DownloadToEpub")
|
|
|
|
local epub_path = ("%s%s.epub"):format(self.output_directory, util.getSafeFilename(epub.title))
|
|
local build_director, err = self:createBuildDirector(epub_path)
|
|
if not build_director then
|
|
logger.dbg("DownloadToEpub: " .. err)
|
|
return false, err
|
|
end
|
|
|
|
info = InfoMessage:new{ text = _("Writing to device…") }
|
|
UIManager:show(info)
|
|
UIManager:forceRePaint()
|
|
UIManager:close(info)
|
|
|
|
logger.dbg("DownloadToEpub: Writing EPUB to " .. epub_path)
|
|
local path_to_epub, err = build_director:construct(epub)
|
|
if not path_to_epub then
|
|
logger.dbg("DownloadToEpub: " .. err)
|
|
return false, err
|
|
end
|
|
|
|
return path_to_epub
|
|
end
|
|
|
|
function EpubBuilder:createWebpage(url)
|
|
local webpage, err = WebPage:new({
|
|
url = url,
|
|
})
|
|
|
|
if err then
|
|
return false, err
|
|
end
|
|
|
|
webpage:build()
|
|
|
|
return webpage
|
|
end
|
|
|
|
function EpubBuilder:createBuildDirector(epub_path)
|
|
local build_director, err = EpubBuildDirector:new()
|
|
|
|
if not build_director then
|
|
return false, err
|
|
end
|
|
|
|
local success, err = build_director:setDestination(epub_path)
|
|
|
|
if not success then
|
|
return false, err
|
|
end
|
|
|
|
return build_director
|
|
end
|
|
|
|
return DownloadToEpub
|