Skip to content

Commit

Permalink
Send2Ebook (receiver) plugin (#3681)
Browse files Browse the repository at this point in the history
  • Loading branch information
mwoz123 authored and Frenzie committed Feb 22, 2018
1 parent 720fd5d commit 25a67a2
Show file tree
Hide file tree
Showing 6 changed files with 268 additions and 17 deletions.
2 changes: 2 additions & 0 deletions frontend/apps/cloudstorage/cloudstorage.lua
Expand Up @@ -282,6 +282,7 @@ function CloudStorage:configCloud(type)
address = fields[2],
username = fields[3],
password = fields[4],
folder = fields[5],
type = "ftp",
url = "/"
})
Expand Down Expand Up @@ -318,6 +319,7 @@ function CloudStorage:editCloudServer(item)
server.address = fields[2]
server.username = fields[3]
server.password = fields[4]
server.folder = fields[5]
cs_servers[i] = server
break
end
Expand Down
30 changes: 13 additions & 17 deletions frontend/apps/cloudstorage/ftp.lua
Expand Up @@ -5,33 +5,21 @@ local MultiInputDialog = require("ui/widget/multiinputdialog")
local ReaderUI = require("apps/reader/readerui")
local Screen = require("device").screen
local UIManager = require("ui/uimanager")
local logger = require("logger")
local util = require("util")
local _ = require("gettext")
local T = require("ffi/util").template

local Ftp = {
}
local function generateUrl(address, user, pass)
local colon_sign = ""
local at_sign = ""
if user ~= "" then
at_sign = "@"
end
if pass ~= "" then
colon_sign = ":"
end
local replace = "://" .. user .. colon_sign .. pass .. at_sign
local url = string.gsub(address, "://", replace)
return url
end
local Ftp = {}

function Ftp:run(address, user, pass, path)
local url = generateUrl(address, user, pass) .. path
local url = FtpApi:generateUrl(address, user, pass) .. path
return FtpApi:listFolder(url, path)
end

function Ftp:downloadFile(item, address, user, pass, path, close)
local url = generateUrl(address, user, pass) .. item.url
local url = FtpApi:generateUrl(address, user, pass) .. item.url
logger.dbg("downloadFile url", url)
local response = FtpApi:downloadFile(url)
if response ~= nil then
path = util.fixUtf8(path, "_")
Expand Down Expand Up @@ -66,6 +54,8 @@ function Ftp:config(item, callback)
local text_username = ""
local hint_password = _("FTP password")
local text_password = ""
local hint_folder = _("FTP folder")
local text_folder = "/"
local title
local text_button_right = _("Add")
if item then
Expand All @@ -75,6 +65,7 @@ function Ftp:config(item, callback)
text_address = item.address
text_username = item.username
text_password = item.password
text_folder = item.folder
else
title = _("Add FTP account")
end
Expand All @@ -101,6 +92,11 @@ function Ftp:config(item, callback)
input_type = "string",
hint = hint_password,
},
{
text = text_folder,
input_type = "string",
hint = hint_folder,
},
},
buttons = {
{
Expand Down
22 changes: 22 additions & 0 deletions frontend/apps/cloudstorage/ftpapi.lua
Expand Up @@ -6,6 +6,20 @@ local url = require("socket.url")
local FtpApi = {
}

function FtpApi:generateUrl(address, user, pass)
local colon_sign = ""
local at_sign = ""
if user ~= "" then
at_sign = "@"
end
if pass ~= "" then
colon_sign = ":"
end
local replace = "://" .. user .. colon_sign .. pass .. at_sign
local generated_url = string.gsub(address, "://", replace)
return generated_url
end

function FtpApi:nlst(u)
local t = {}
local p = url.parse(u)
Expand Down Expand Up @@ -69,4 +83,12 @@ function FtpApi:downloadFile(file_path)
return ftp.get(file_path ..";type=i")
end

function FtpApi:delete(file_path)
local p = url.parse(file_path)
p.argument = string.gsub(p.path, "^/", "")
p.command = "dele"
p.check = 250
return ftp.command(p)
end

return FtpApi
1 change: 1 addition & 0 deletions frontend/ui/elements/filemanager_menu_order.lua
Expand Up @@ -37,6 +37,7 @@ local order = {
"cloud_storage",
"read_timer",
"news_downloader",
"send2ebook",
"----------------------------",
"more_plugins",
"----------------------------",
Expand Down
1 change: 1 addition & 0 deletions frontend/ui/elements/reader_menu_order.lua
Expand Up @@ -58,6 +58,7 @@ local order = {
"progress_sync",
"zsync",
"news_downloader",
"send2ebook",
"----------------------------",
"more_plugins",
},
Expand Down
229 changes: 229 additions & 0 deletions plugins/send2ebook.koplugin/main.lua
@@ -0,0 +1,229 @@
local DataStorage = require("datastorage")
local DocSettings = require("frontend/docsettings")
local ReadHistory = require("readhistory")
local FFIUtil = require("ffi/util")
local Ftp = require("apps/cloudstorage/ftp")
local FtpApi = require("apps/cloudstorage/ftpapi")
local InfoMessage = require("ui/widget/infomessage")
local LuaSettings = require("frontend/luasettings")
local UIManager = require("ui/uimanager")
local NetworkMgr = require("ui/network/manager")
local WidgetContainer = require("ui/widget/container/widgetcontainer")
local logger = require("logger")
local util = require("util")
local _ = require("gettext")
local T = FFIUtil.template

local Send2Ebook = WidgetContainer:new{}

local initialized = false
local wifi_enabled_before_action = true
local send2ebook_config_file = "send2ebook_settings.lua"
local config_key_custom_dl_dir = "custom_dl_dir";
local default_download_dir_name = "send2ebook"
local supported_ftp_file_type = ".epub"
local download_dir_path
local send2ebook_settings

local function stringEnds(str,suffix)
return suffix=="" or string.sub(str,-string.len(suffix))==suffix
end

function Send2Ebook:downloadFileAndRemove(connection_url, remote_path, local_download_path)
local url = connection_url .. remote_path
local response = FtpApi:downloadFile(url)

if response ~= nil then
local_download_path = util.fixUtf8(local_download_path, "_")
local file = io.open(local_download_path, "w")
file:write(response)
file:close()
FtpApi:delete(url)
return 1
else
logger.err("Send2Ebook: Error. Invalid connection data? ")
return 0
end
end

-- TODO: implement as NetworkMgr:afterWifiAction with configuration options
function Send2Ebook:afterWifiAction()
if not wifi_enabled_before_action then
NetworkMgr:promptWifiOff()
end
end

function Send2Ebook:init()
self.ui.menu:registerToMainMenu(self)
end

function Send2Ebook:addToMainMenu(menu_items)
self:lazyInitialization()
menu_items.send2ebook = {
text = _("Send2Ebook (Receiver)"),
sub_item_table = {
{
text = _("Download and remove from server"),
callback = function()
if not NetworkMgr:isOnline() then
wifi_enabled_before_action = false
NetworkMgr:beforeWifiAction(self.process)
else
self:process()
end
end,
},
{
text = _("Go to download folder"),
callback = function()
local FileManager = require("apps/filemanager/filemanager")
if FileManager.instance then
FileManager.instance:reinit(download_dir_path)
else
FileManager:showFiles(download_dir_path)
end
end,
},
{
text = _("Remove read (opened) articles"),
callback = self.removeReadActicles,
},
{
text = _("Set custom download directory"),
callback = self.setCustomDownloadDirectory,
},
{
text = _("Settings"),
callback = self.editFtpConnection,
},
{
text = _("Help"),
callback = function()
UIManager:show(InfoMessage:new{
text = T(_('Send2Ebook lets you send articles found on PC/Android phone to your Ebook reader (using ftp server).\n\nMore details: https://github.com/mwoz123/send2ebook\n\nDownloads to local folder: %1'), download_dir_path)
})
end,
},
},
}
end

function Send2Ebook:lazyInitialization()
if not initialized then
logger.dbg("Send2Ebook: obtaining download folder")
send2ebook_settings = LuaSettings:open(("%s/%s"):format(DataStorage:getSettingsDir(), send2ebook_config_file))
if send2ebook_settings:has(config_key_custom_dl_dir) then
download_dir_path = send2ebook_settings:readSetting(config_key_custom_dl_dir)
else
download_dir_path = ("%s/%s/"):format(DataStorage:getFullDataDir(), default_download_dir_name)
end

if not lfs.attributes(download_dir_path, "mode") then
logger.dbg("Send2Ebook: Creating initial directory")
lfs.mkdir(download_dir_path)
end
end
end

function Send2Ebook:process()
local info = InfoMessage:new{ text = _("Connecting …") }
UIManager:show(info)
logger.dbg("Send2Ebook: force repaint due to upcoming blocking calls")
UIManager:forceRePaint()
UIManager:close(info)

local count = 1
local ftp_config = send2ebook_settings:readSetting("ftp_config") or {address="Please setup ftp in settings", username="", password="", folder=""}

local connection_url = FtpApi:generateUrl(ftp_config.address, ftp_config.username, ftp_config.password)

local ftp_files_table = FtpApi:listFolder(connection_url .. ftp_config.folder, ftp_config.folder) --args looks strange but otherwise resonse with invalid paths

if not ftp_files_table then
info = InfoMessage:new{ text = T(_("Could not get file list for server: %1, user: %2, folder: %3"), ftp_config.address, ftp_config.username, ftp_config.folder) }
else
local total_entries = table.getn(ftp_files_table)
logger.dbg("Send2Ebook: total_entries ", total_entries)
if total_entries > 1 then total_entries = total_entries -2 end --remove result "../" (upper folder) and "./" (current folder)
for idx, ftp_file in ipairs(ftp_files_table) do
logger.dbg("Send2Ebook: processing ftp_file:", ftp_file)
if ftp_file["type"] == "file" and stringEnds(ftp_file["text"], supported_ftp_file_type) then

info = InfoMessage:new{ text = T(_("Processing %1/%2"), count, total_entries) }
UIManager:show(info)
UIManager:forceRePaint()
UIManager:close(info)

local remote_file_path = ftp_file["url"]
logger.dbg("Send2Ebook: remote_file_path", remote_file_path)
local local_file_path = download_dir_path .. ftp_file["text"]
count = count + Send2Ebook:downloadFileAndRemove(connection_url, remote_file_path, local_file_path)
end
info = InfoMessage:new{ text = T(_("Processing finished. Success: %1"), count -1) }
end
end
UIManager:show(info)
Send2Ebook:afterWifiAction()
end

function Send2Ebook:removeReadActicles()
logger.dbg("Send2Ebook: Removing read articles from :", download_dir_path)
for entry in lfs.dir(download_dir_path) do
if entry ~= "." and entry ~= ".." then
local entry_path = download_dir_path .. entry
if DocSettings:hasSidecarFile(entry_path) then
local entry_mode = lfs.attributes(entry_path, "mode")
if entry_mode == "file" then
os.remove(entry_path)
local sdr_dir = DocSettings:getSidecarDir(entry_path)
logger.dbg("Send2Ebook: sdr dir to be removed:", sdr_dir)
FFIUtil.purgeDir(sdr_dir)
end
end
end
end
UIManager:show(InfoMessage:new{
text = _("All read articles removed.")
})
end

function Send2Ebook:setCustomDownloadDirectory()
UIManager:show(InfoMessage:new{
text = _("To select a folder press down and hold it for 1 second.")
})
require("ui/downloadmgr"):new{
title = _("Choose download directory"),
onConfirm = function(path)
logger.dbg("Send2Ebook: set download directory to: ", path)
send2ebook_settings:saveSetting(config_key_custom_dl_dir, ("%s/"):format(path))
send2ebook_settings:flush()

initialized = false
self:lazyInitialization()
end,
}:chooseDir()
end

function Send2Ebook:editFtpConnection()
local item = send2ebook_settings:readSetting("ftp_config") or {text="ignore this field, it's not used here;) fill rest", address="ftp://", username="",password="" , folder="/"}
local callbackEdit = function(updated_config, fields)
local data = {text=fields[1], address=fields[2], username=fields[3],password=fields[4] , folder=fields[5]}
send2ebook_settings:saveSetting("ftp_config", data)
send2ebook_settings:flush()
initialized = false
Send2Ebook:lazyInitialization()
end
Ftp:config(item, callbackEdit)
end

function Send2Ebook:onCloseDocument()
local document_full_path = self.ui.document.file
if document_full_path and download_dir_path == string.sub(document_full_path, 1, string.len(download_dir_path)) then
logger.dbg("Send2Ebook: document_full_path:", document_full_path)
logger.dbg("Send2Ebook: download_dir_path:", download_dir_path)
logger.dbg("Send2Ebook: removing Send2Ebook file from history.")
ReadHistory:removeItemByPath(document_full_path)
end
end

return Send2Ebook

0 comments on commit 25a67a2

Please sign in to comment.