2020-01-04 00:18:51 +00:00
local BD = require ( " ui/bidi " )
2017-04-19 15:59:45 +00:00
local DataStorage = require ( " datastorage " )
2017-10-27 21:00:49 +00:00
local ReadHistory = require ( " readhistory " )
2017-04-19 15:59:45 +00:00
local FFIUtil = require ( " ffi/util " )
2021-09-13 19:04:06 +00:00
local FeedView = require ( " feed_view " )
2022-01-21 18:23:21 +00:00
local FeedSource = require ( " feed_source " )
2017-08-11 14:28:25 +00:00
local InfoMessage = require ( " ui/widget/infomessage " )
local LuaSettings = require ( " frontend/luasettings " )
local UIManager = require ( " ui/uimanager " )
2021-09-13 19:04:06 +00:00
local KeyValuePage = require ( " ui/widget/keyvaluepage " )
local InputDialog = require ( " ui/widget/inputdialog " )
local MultiConfirmBox = require ( " ui/widget/multiconfirmbox " )
2017-10-22 07:11:23 +00:00
local NetworkMgr = require ( " ui/network/manager " )
2021-09-13 19:04:06 +00:00
local Persist = require ( " persist " )
2017-08-11 14:28:25 +00:00
local WidgetContainer = require ( " ui/widget/container/widgetcontainer " )
local logger = require ( " logger " )
local util = require ( " util " )
local _ = require ( " gettext " )
local T = FFIUtil.template
2017-04-19 15:59:45 +00:00
2018-08-17 18:54:11 +00:00
local NewsDownloader = WidgetContainer : new {
2021-09-13 19:04:06 +00:00
name = " news_downloader " ,
initialized = false ,
feed_config_file = " feed_config.lua " ,
feed_config_path = nil ,
news_config_file = " news_settings.lua " ,
2022-01-21 18:23:21 +00:00
news_history_file = " news_history.lua " ,
2021-09-13 19:04:06 +00:00
settings = nil ,
2022-01-21 18:23:21 +00:00
history = nil ,
2021-09-13 19:04:06 +00:00
download_dir_name = " news " ,
download_dir = nil ,
config_key_custom_dl_dir = " custom_dl_dir " ,
empty_feed = {
[ 1 ] = " https:// " ,
limit = 5 ,
download_full_article = true ,
include_images = true ,
enable_filter = false ,
2022-01-21 18:23:21 +00:00
filter_element = " " ,
volumize = false
2021-09-13 19:04:06 +00:00
} ,
kv = { }
2018-08-17 18:54:11 +00:00
}
2017-04-19 15:59:45 +00:00
function NewsDownloader : init ( )
self.ui . menu : registerToMainMenu ( self )
end
function NewsDownloader : addToMainMenu ( menu_items )
2017-05-08 20:15:42 +00:00
menu_items.news_downloader = {
2021-09-13 19:04:06 +00:00
text = _ ( " News downloader (RSS/Atom) " ) ,
sub_item_table_func = function ( )
return self : getSubMenuItems ( )
end ,
}
end
function NewsDownloader : getSubMenuItems ( )
self : lazyInitialization ( )
local sub_item_table
sub_item_table = {
{
text = _ ( " Go to news folder " ) ,
callback = function ( )
self : openDownloadsFolder ( )
end ,
} ,
{
text = _ ( " Sync news feeds " ) ,
keep_menu_open = true ,
callback = function ( touchmenu_instance )
2022-01-21 18:23:21 +00:00
NetworkMgr : runWhenOnline (
function ( ) self : syncAllFeedsWithUI (
touchmenu_instance ,
function ( feed_message )
-- Callback to fire after sync is finished
local UI = require ( " ui/trapper " )
-- This callback is called after the
-- processing is complete.
--
-- Clear the info widgets before displaying the next ui widget.
-- UI:clear()
-- Ask the user if they want to go to their downloads folder
-- or if they'd rather remain at the menu.
feed_message = feed_message _ ( " Go to downloaders folder? " )
local should_go_to_downloads = UI : confirm (
feed_message ,
_ ( " Close " ) ,
_ ( " Go to downloads " )
)
if should_go_to_downloads then
-- Go to downloads folder.
UI : clear ( )
self : openDownloadsFolder ( )
touchmenu_instance : closeMenu ( )
NetworkMgr : afterWifiAction ( )
return
else
-- Return to the menu.
NetworkMgr : afterWifiAction ( )
return
end
end
) end )
2021-09-13 19:04:06 +00:00
end ,
} ,
{
text = _ ( " Edit news feeds " ) ,
keep_menu_open = true ,
callback = function ( )
local Trapper = require ( " ui/trapper " )
Trapper : wrap ( function ( )
self : viewFeedList ( )
end )
end ,
} ,
{
text = _ ( " Settings " ) ,
sub_item_table = {
{
text = _ ( " Set download folder " ) ,
keep_menu_open = true ,
callback = function ( ) self : setCustomDownloadDirectory ( ) end ,
} ,
{
text = _ ( " Delete all downloaded items " ) ,
keep_menu_open = true ,
callback = function ( )
local Trapper = require ( " ui/trapper " )
Trapper : wrap ( function ( )
local should_delete = Trapper : confirm (
_ ( " Are you sure you want to delete all downloaded items? " ) ,
_ ( " Cancel " ) ,
_ ( " Delete " )
)
if should_delete then
self : removeNewsButKeepFeedConfig ( )
2022-01-21 18:23:21 +00:00
-- Move user to the downloads folder to avoid an error where they
-- are within a feed folder which we have just deleted.
self : openDownloadsFolder ( )
2021-09-13 19:04:06 +00:00
Trapper : reset ( )
else
Trapper : reset ( )
end
end )
end ,
2018-01-17 17:16:11 +00:00
} ,
2017-06-29 18:40:42 +00:00
} ,
2021-09-13 19:04:06 +00:00
} ,
{
text = _ ( " About " ) ,
keep_menu_open = true ,
callback = function ( )
UIManager : show ( InfoMessage : new {
text = T ( _ ( " News downloader retrieves RSS and Atom news entries and stores them to: \n %1 \n \n Each entry is a separate EPUB file that can be browsed by KOReader. \n Feeds can be configured with download limits and other customization through the Edit Feeds menu item. " ) ,
BD.dirpath ( self.download_dir ) )
} )
end ,
2017-04-19 15:59:45 +00:00
} ,
}
2021-09-13 19:04:06 +00:00
return sub_item_table
2017-04-19 15:59:45 +00:00
end
2022-01-21 18:23:21 +00:00
-- lazyInitialization sets up our variables to point to the
2021-09-14 05:42:32 +00:00
-- Downloads folder and the feeds configuration file.
2017-05-14 08:46:12 +00:00
function NewsDownloader : lazyInitialization ( )
2021-09-13 19:04:06 +00:00
if not self.initialized then
2017-05-14 08:46:12 +00:00
logger.dbg ( " NewsDownloader: obtaining news folder " )
2021-09-13 19:04:06 +00:00
self.settings = LuaSettings : open ( ( " %s/%s " ) : format ( DataStorage : getSettingsDir ( ) , self.news_config_file ) )
-- Check to see if a custom download directory has been set.
if self.settings : has ( self.config_key_custom_dl_dir ) then
self.download_dir = self.settings : readSetting ( self.config_key_custom_dl_dir )
2017-05-14 08:46:12 +00:00
else
2021-09-13 19:04:06 +00:00
self.download_dir =
( " %s/%s/ " ) : format (
DataStorage : getFullDataDir ( ) ,
self.download_dir_name )
2017-05-14 08:46:12 +00:00
end
2022-01-21 18:23:21 +00:00
logger.dbg ( " NewsDownloader: initializing download history " )
self.history = LuaSettings : open ( ( " %s/%s " ) : format ( DataStorage : getSettingsDir ( ) , self.news_history_file ) )
2021-09-13 19:04:06 +00:00
logger.dbg ( " NewsDownloader: Custom directory set to: " , self.download_dir )
-- If the directory doesn't exist we will create it.
if not lfs.attributes ( self.download_dir , " mode " ) then
2017-05-14 08:46:12 +00:00
logger.dbg ( " NewsDownloader: Creating initial directory " )
2021-09-13 19:04:06 +00:00
lfs.mkdir ( self.download_dir )
2017-05-14 08:46:12 +00:00
end
2021-09-13 19:04:06 +00:00
-- Now set the path to the feed configuration file.
self.feed_config_path = self.download_dir .. self.feed_config_file
-- If the configuration file doesn't exist create it.
if not lfs.attributes ( self.feed_config_path , " mode " ) then
2017-05-14 08:46:12 +00:00
logger.dbg ( " NewsDownloader: Creating initial feed config. " )
2021-09-13 19:04:06 +00:00
FFIUtil.copyFile ( FFIUtil.joinPath ( self.path , self.feed_config_file ) ,
self.feed_config_path )
2017-05-14 08:46:12 +00:00
end
2021-09-13 19:04:06 +00:00
self.initialized = true
2017-05-14 08:46:12 +00:00
end
end
2022-01-21 18:23:21 +00:00
-- This function loads the config file. If the config is not available
-- then this function includes prompts for handling that.
function NewsDownloader : loadConfig ( )
2019-04-30 22:37:03 +00:00
local UI = require ( " ui/trapper " )
2017-05-14 08:46:12 +00:00
logger.dbg ( " force repaint due to upcoming blocking calls " )
2022-01-21 18:23:21 +00:00
-- Check if the feed config file exists
2021-09-13 19:04:06 +00:00
local ok , feed_config = pcall ( dofile , self.feed_config_path )
2017-04-19 15:59:45 +00:00
if not ok or not feed_config then
2019-04-30 22:37:03 +00:00
UI : info ( T ( _ ( " Invalid configuration file. Detailed error message: \n %1 " ) , feed_config ) )
2022-01-21 18:23:21 +00:00
return false
2017-04-19 15:59:45 +00:00
end
2021-09-13 19:04:06 +00:00
-- If the file contains no table elements, then the user hasn't set any feeds.
2017-04-19 15:59:45 +00:00
if # feed_config <= 0 then
2021-09-13 19:04:06 +00:00
logger.err ( " NewsDownloader: empty feed list. " , self.feed_config_path )
local should_edit_feed_list = UI : confirm (
T ( _ ( " Feed list is empty. If you want to download news, you'll have to add a feed first. " ) ) ,
_ ( " Close " ) ,
_ ( " Edit feed list " )
)
if should_edit_feed_list then
-- Show the user a blank feed view so they can
-- add a feed to their list.
local feed_item_vc = FeedView : getItem (
1 ,
self.empty_feed ,
function ( id , edit_key , value )
self : editFeedAttribute ( id , edit_key , value )
end
)
self : viewFeedItem (
feed_item_vc
)
end
2022-01-21 18:23:21 +00:00
return false
2017-05-08 20:15:42 +00:00
end
2022-01-21 18:23:21 +00:00
-- If we made it this far, then the feed config is valid
-- and the next step is to process its contents
return feed_config
2017-04-19 15:59:45 +00:00
end
2022-01-21 18:23:21 +00:00
function NewsDownloader : syncAllFeedsWithUI ( touchmenu_instance , callback )
2019-04-30 22:37:03 +00:00
local Trapper = require ( " ui/trapper " )
Trapper : wrap ( function ( )
2022-01-21 18:23:21 +00:00
local UI = require ( " ui/trapper " )
-- Get the config
local config = self : loadConfig ( )
local sync_errors = { }
-- Get the HTML for the feeds
local feedSource = FeedSource : new { }
-- Get the initialized feeds list
local initialized_feeds = feedSource : getInitializedFeeds (
config ,
function ( progress_message )
-- This callback relays updates to the UI
UI : info ( progress_message )
end ,
function ( error_message )
table.insert (
sync_errors ,
error_message
)
end
)
-- In this block, each feed item will be its own
-- epub complete with title and chapters
local epubs_to_make = { }
local epubs_successfully_created = { }
local feed_history = { }
for feed_index , feed in pairs ( initialized_feeds ) do
-- Go through each feed and make new entry
local items_content = feedSource : getItemsContent (
feed ,
function ( progress_message )
UI : info ( progress_message )
end ,
function ( error_message )
table.insert (
sync_errors ,
error_message
)
end
2021-09-13 19:04:06 +00:00
)
2017-05-08 20:15:42 +00:00
2022-01-21 18:23:21 +00:00
local volumize = feed.config . volumize ~= false
local chapters = { }
local feed_title = feedSource : getFeedTitleWithDate ( feed )
local feed_id = feed.config [ 1 ] -- The url.
local sub_dir = feedSource : getFeedTitle ( feed.document . title )
local item_history = { }
2017-05-14 08:46:12 +00:00
2022-01-21 18:23:21 +00:00
for content_index , content in pairs ( items_content ) do
-- Check to see if we've already downloaded this item.
local history_for_feed = self.history : child ( feed_id )
2017-04-19 15:59:45 +00:00
2022-01-21 18:23:21 +00:00
if history_for_feed : has ( content.md5 ) then
logger.dbg ( " NewsDownloader: " , " Item already downloaded " )
UI : info ( _ ( " Skipping downloaded item " ) )
else
local abs_path = feedSource : getEpubOutputDir (
self.download_dir ,
sub_dir ,
content.item_title
)
-- Not sure the slug returned is what we want.
-- Should be something like 2022_09_20-ArticleTitle
table.insert (
chapters ,
{
title = content.item_title ,
slug = content.item_slug ,
md5 = content.md5 ,
html = content.html ,
images = content.images
}
)
if not volumize then
-- We're not volumizing, so each chapter
-- will be its own epub.
table.insert (
epubs_to_make ,
{
title = content.item_title ,
chapters = chapters ,
abs_path = abs_path ,
id = feed_id ,
}
)
-- Reset the chapters list.
chapters = { }
end
table.insert (
item_history ,
content.md5
)
end
end
-- We're volumizing, so all of the chapters we collected
-- get added to a single epub.
if volumize and # chapters > 0 then
local abs_path = feedSource : getEpubOutputDir (
self.download_dir ,
sub_dir ,
feed_title
)
2018-04-12 14:05:50 +00:00
2022-01-21 18:23:21 +00:00
table.insert (
epubs_to_make ,
{
title = feed_title ,
chapters = chapters ,
abs_path = abs_path ,
id = feed_id ,
}
)
end
2018-04-12 14:05:50 +00:00
2022-01-21 18:23:21 +00:00
feed_history [ feed_id ] = item_history
end
2017-08-11 14:28:25 +00:00
2022-01-21 18:23:21 +00:00
-- Make each EPUB.
for epub_index , epub in pairs ( epubs_to_make ) do
local ok = feedSource : createEpub (
epub.title ,
epub.chapters ,
epub.abs_path ,
function ( progress_message )
UI : info ( progress_message )
end ,
function ( error_message )
table.insert (
sync_errors ,
error_message
)
end
)
if ok then
-- Save the hashes to the setting for this feed.
local hashes_to_save = feed_history [ epub.id ]
local history_for_feed = self.history : child ( epub.id )
for index , hash in ipairs ( hashes_to_save ) do
if history_for_feed : hasNot ( hash ) then
history_for_feed : saveSetting ( hash , true )
end
end
-- Add the epub title to the successfully created table.
table.insert (
epubs_successfully_created ,
epub.title
)
else
table.insert (
sync_errors ,
T (
_ ( ' Error building EPUB %1 ' ) ,
epub.title
)
)
end
end
2017-05-08 20:15:42 +00:00
2022-01-21 18:23:21 +00:00
logger.dbg ( epubs_to_make )
2017-10-26 20:44:03 +00:00
2022-01-21 18:23:21 +00:00
self.history : flush ( )
-- Relay any errors
for index , error_message in pairs ( sync_errors ) do
UI : confirm (
error_message ,
_ ( " Continue " ) ,
" "
)
end
local message = ( # epubs_successfully_created == 0 ) and
_ ( " Sync complete. No new EPUBs created. " ) or
T ( _ ( " Sync complete. EPUBs created: %1 " ) ,
table.concat ( epubs_successfully_created , " , " ) )
callback ( message )
end )
2017-10-26 20:44:03 +00:00
end
2017-05-14 08:46:12 +00:00
function NewsDownloader : removeNewsButKeepFeedConfig ( )
2021-09-13 19:04:06 +00:00
logger.dbg ( " NewsDownloader: Removing news from : " , self.download_dir )
for entry in lfs.dir ( self.download_dir ) do
if entry ~= " . " and entry ~= " .. " and entry ~= self.feed_config_file then
local entry_path = self.download_dir .. " / " .. entry
2017-05-14 08:46:12 +00:00
local entry_mode = lfs.attributes ( entry_path , " mode " )
if entry_mode == " file " then
2018-08-07 19:03:43 +00:00
os.remove ( entry_path )
2017-05-14 08:46:12 +00:00
elseif entry_mode == " directory " then
FFIUtil.purgeDir ( entry_path )
end
end
end
UIManager : show ( InfoMessage : new {
2022-01-21 18:23:21 +00:00
text = _ ( " All downloaded news feed items deleted. To download these again in the future, reset the feed history. " )
2017-05-14 08:46:12 +00:00
} )
end
function NewsDownloader : setCustomDownloadDirectory ( )
require ( " ui/downloadmgr " ) : new {
2021-09-13 19:04:06 +00:00
onConfirm = function ( path )
logger.dbg ( " NewsDownloader: set download directory to: " , path )
self.settings : saveSetting ( self.config_key_custom_dl_dir , ( " %s/ " ) : format ( path ) )
self.settings : flush ( )
logger.dbg ( " NewsDownloader: Coping to new download folder previous self.feed_config_file from: " , self.feed_config_path )
FFIUtil.copyFile ( self.feed_config_path , ( " %s/%s " ) : format ( path , self.feed_config_file ) )
self.initialized = false
self : lazyInitialization ( )
end ,
} : chooseDir ( )
end
function NewsDownloader : viewFeedList ( )
-- Protected call to see if feed config path returns a file that can be opened.
local ok , feed_config = pcall ( dofile , self.feed_config_path )
if not ok or not feed_config then
2022-01-21 18:23:21 +00:00
local UI = require ( " ui/trapper " )
2021-09-14 05:42:32 +00:00
local change_feed_config = UI : confirm (
2021-09-26 10:44:43 +00:00
_ ( " Could not open feed list. Feeds configuration file is invalid. " ) ,
2021-09-13 19:04:06 +00:00
_ ( " Close " ) ,
_ ( " View file " )
)
if change_feed_config then
self : changeFeedConfig ( )
end
return
end
local view_content = FeedView : getList (
feed_config ,
function ( feed_item_vc )
self : viewFeedItem (
feed_item_vc
)
end ,
function ( id , edit_key , value )
self : editFeedAttribute ( id , edit_key , value )
end ,
2022-01-21 18:23:21 +00:00
function ( id , action )
if action == FeedView.ACTION_DELETE_FEED then
self : deleteFeed ( id )
elseif action == FeedView.ACTION_RESET_HISTORY then
local Trapper = require ( " ui/trapper " )
Trapper : wrap ( function ( )
local should_reset = Trapper : confirm (
_ ( " Are you sure you want to reset the feed history? Proceeding will cause items to be re-downloaded next time you sync. " ) ,
_ ( " Cancel " ) ,
_ ( " Reset " )
)
if should_reset then
self : resetFeedHistory ( id )
Trapper : reset ( )
else
Trapper : reset ( )
end
end )
end
2021-09-13 19:04:06 +00:00
end
)
-- Add a "Add new feed" button with callback
table.insert (
view_content ,
{
_ ( " Add new feed " ) ,
" " ,
callback = function ( )
-- Prepare the view with all the callbacks for editing the attributes
local feed_item_vc = FeedView : getItem (
# feed_config + 1 ,
self.empty_feed ,
function ( id , edit_key , value )
self : editFeedAttribute ( id , edit_key , value )
end
)
self : viewFeedItem (
feed_item_vc
)
end
}
)
-- Show the list of feeds.
if # self.kv ~= 0 then
UIManager : close ( self.kv )
end
self.kv = KeyValuePage : new {
2021-09-26 10:44:43 +00:00
title = _ ( " RSS/Atom feeds " ) ,
2021-09-13 19:04:06 +00:00
value_overflow_align = " right " ,
kv_pairs = view_content ,
callback_return = function ( )
UIManager : close ( self.kv )
end
}
UIManager : show ( self.kv )
end
function NewsDownloader : viewFeedItem ( data )
if # self.kv ~= 0 then
UIManager : close ( self.kv )
end
self.kv = KeyValuePage : new {
title = _ ( " Edit Feed " ) ,
value_overflow_align = " left " ,
kv_pairs = data ,
callback_return = function ( )
self : viewFeedList ( )
end
}
UIManager : show ( self.kv )
end
function NewsDownloader : editFeedAttribute ( id , key , value )
local kv = self.kv
2022-01-21 18:23:21 +00:00
-- This block determines what kind of UI to produce, or action to run,
-- based on the key value. Some values need an input dialog, others need
-- a Yes/No dialog.
if key == FeedView.RESET_HISTORY then
-- Show a "are you sure" box.
-- Reset the history
self.history : removeTableItem ( value , 1 )
self.history : flush ( )
elseif key == FeedView.URL
2021-09-13 19:04:06 +00:00
or key == FeedView.LIMIT
or key == FeedView.FILTER_ELEMENT then
local title
local input_type
local description
if key == FeedView.URL then
title = _ ( " Edit feed URL " )
input_type = " string "
elseif key == FeedView.LIMIT then
title = _ ( " Edit feed limit " )
description = _ ( " Set to 0 for no limit to how many items are downloaded " )
input_type = " number "
elseif key == FeedView.FILTER_ELEMENT then
title = _ ( " Edit filter element. " )
description = _ ( " Filter based on the given CSS selector. E.g.: name_of_css.element.class " )
input_type = " string "
else
return false
end
local input_dialog
input_dialog = InputDialog : new {
title = title ,
input = value ,
input_type = input_type ,
description = description ,
buttons = {
{
{
text = _ ( " Cancel " ) ,
callback = function ( )
UIManager : close ( input_dialog )
UIManager : show ( kv )
end ,
} ,
{
text = _ ( " Save " ) ,
is_enter_default = true ,
callback = function ( )
UIManager : close ( input_dialog )
self : updateFeedConfig ( id , key , input_dialog : getInputValue ( ) )
end ,
} ,
}
} ,
}
UIManager : show ( input_dialog )
input_dialog : onShowKeyboard ( )
return true
else
local text
if key == FeedView.DOWNLOAD_FULL_ARTICLE then
text = _ ( " Download full article? " )
elseif key == FeedView.INCLUDE_IMAGES then
text = _ ( " Include images? " )
elseif key == FeedView.ENABLE_FILTER then
text = _ ( " Enable CSS filter? " )
2022-01-21 18:23:21 +00:00
elseif key == FeedView.VOLUMIZE then
text = _ ( " Volumize feed? " )
2021-09-13 19:04:06 +00:00
end
local multi_box
multi_box = MultiConfirmBox : new {
text = text ,
choice1_text = _ ( " Yes " ) ,
choice1_callback = function ( )
UIManager : close ( multi_box )
self : updateFeedConfig ( id , key , true )
end ,
choice2_text = _ ( " No " ) ,
choice2_callback = function ( )
UIManager : close ( multi_box )
self : updateFeedConfig ( id , key , false )
end ,
cancel_callback = function ( )
UIManager : close ( multi_box )
UIManager : show ( kv )
end ,
}
UIManager : show ( multi_box )
end
end
function NewsDownloader : updateFeedConfig ( id , key , value )
2021-09-14 05:42:32 +00:00
local UI = require ( " ui/trapper " )
2021-09-13 19:04:06 +00:00
-- Because this method is called at the menu,
-- we might not have an active view. So this conditional
-- statement avoids closing a null reference.
if # self.kv ~= 0 then
UIManager : close ( self.kv )
end
-- It's possible that we will get a null value.
-- This block catches that possibility.
if id ~= nil and key ~= nil and value ~= nil then
-- This logger is a bit opaque because T() wasn't playing nice with booleans
logger.dbg ( " Newsdownloader: attempting to update config: " )
else
logger.dbg ( " Newsdownloader: null value supplied to update. Not updating config " )
return
end
local ok , feed_config = pcall ( dofile , self.feed_config_path )
2022-01-21 18:23:21 +00:00
2021-09-13 19:04:06 +00:00
if not ok or not feed_config then
UI : info ( T ( _ ( " Invalid configuration file. Detailed error message: \n %1 " ) , feed_config ) )
return
end
-- If the file contains no table elements, then the user hasn't set any feeds.
if # feed_config <= 0 then
logger.dbg ( " NewsDownloader: empty feed list. " , self.feed_config_path )
end
-- Check to see if the id is larger than the number of feeds. If it is,
-- then we know this is a new add. Insert the base array.
if id > # feed_config then
table.insert (
feed_config ,
self.empty_feed
)
end
local new_config = { }
-- In this loop, we cycle through the feed items. A series of
-- conditionals checks to see if we are at the right id
-- and key (i.e.: the key that triggered this function.
-- If we are at the right spot, we overrite (or create) the value
for idx , feed in ipairs ( feed_config ) do
-- Check to see if this is the correct feed to update.
if idx == id then
if key == FeedView.URL then
if feed [ 1 ] then
-- If the value exists, then it's been set. So all we do
-- is overwrite the value.
feed [ 1 ] = value
else
-- If the value doesn't exist, then we need to set it.
-- So we insert it into the table.
table.insert (
feed ,
{
value
}
)
end
elseif key == FeedView.LIMIT then
2022-01-21 18:23:21 +00:00
feed.limit = value
2021-09-13 19:04:06 +00:00
elseif key == FeedView.DOWNLOAD_FULL_ARTICLE then
2022-01-21 18:23:21 +00:00
feed.download_full_article = value
2021-09-13 19:04:06 +00:00
elseif key == FeedView.INCLUDE_IMAGES then
2022-01-21 18:23:21 +00:00
feed.include_images = value
2021-09-13 19:04:06 +00:00
elseif key == FeedView.ENABLE_FILTER then
2022-01-21 18:23:21 +00:00
feed.enable_filter = value
2021-09-13 19:04:06 +00:00
elseif key == FeedView.FILTER_ELEMENT then
2022-01-21 18:23:21 +00:00
feed.filter_element = value
elseif key == FeedView.VOLUMIZE then
feed.volumize = value
2021-09-13 19:04:06 +00:00
end
end
-- Now we insert the updated (or newly created) feed into the
-- new config feed that we're building in this loop.
table.insert (
new_config ,
feed
)
end
-- Save the config
logger.dbg ( " NewsDownloader: config to save " , new_config )
self : saveConfig ( new_config )
-- Refresh the view
local feed_item_vc = FeedView : getItem (
id ,
new_config [ id ] ,
2021-09-14 05:42:32 +00:00
function ( cb_id , cb_edit_key , cb_value )
self : editFeedAttribute ( cb_id , cb_edit_key , cb_value )
2022-01-21 18:23:21 +00:00
end ,
function ( feed_id , action )
if action == FeedView.ACTION_DELETE_FEED then
self : deleteFeed ( feed_id )
elseif action == FeedView.ACTION_RESET_HISTORY then
local Trapper = require ( " ui/trapper " )
Trapper : wrap ( function ( )
local should_reset = Trapper : confirm (
_ ( " Are you sure you want to reset the feed history? Proceeding will cause items to be re-downloaded next time you sync. " ) ,
_ ( " Cancel " ) ,
_ ( " Reset " )
)
if should_reset then
self : resetFeedHistory ( id )
Trapper : reset ( )
else
Trapper : reset ( )
end
end )
end
2021-09-13 19:04:06 +00:00
end
)
self : viewFeedItem (
feed_item_vc
)
end
function NewsDownloader : deleteFeed ( id )
2021-09-14 05:42:32 +00:00
local UI = require ( " ui/trapper " )
2021-09-13 19:04:06 +00:00
logger.dbg ( " Newsdownloader: attempting to delete feed " )
-- Check to see if we can get the config file.
local ok , feed_config = pcall ( dofile , self.feed_config_path )
2022-01-21 18:23:21 +00:00
2021-09-13 19:04:06 +00:00
if not ok or not feed_config then
UI : info ( T ( _ ( " Invalid configuration file. Detailed error message: \n %1 " ) , feed_config ) )
return
end
-- In this loop, we cycle through the feed items. A series of
-- conditionals checks to see if we are at the right id
-- and key (i.e.: the key that triggered this function.
-- If we are at the right spot, we overrite (or create) the value
local new_config = { }
2022-01-21 18:23:21 +00:00
2021-09-13 19:04:06 +00:00
for idx , feed in ipairs ( feed_config ) do
-- Check to see if this is the correct feed to update.
if idx ~= id then
table.insert (
new_config ,
feed
)
end
end
-- Save the config
local Trapper = require ( " ui/trapper " )
2022-01-21 18:23:21 +00:00
2021-09-13 19:04:06 +00:00
Trapper : wrap ( function ( )
logger.dbg ( " NewsDownloader: config to save " , new_config )
self : saveConfig ( new_config )
end )
-- Refresh the view
self : viewFeedList ( )
end
2022-01-21 18:23:21 +00:00
function NewsDownloader : resetFeedHistory ( url )
logger.dbg ( " Newsdownloader: attempting to reset feed history " )
self.history : saveSetting ( url , { } )
self.history : flush ( )
-- Refresh the view
self : viewFeedList ( )
end
2021-09-13 19:04:06 +00:00
function NewsDownloader : saveConfig ( config )
local UI = require ( " ui/trapper " )
2021-09-26 10:44:43 +00:00
UI : info ( _ ( " Saving news feed list… " ) )
2021-09-13 19:04:06 +00:00
local persist = Persist : new {
path = self.feed_config_path
}
local ok = persist : save ( config )
if not ok then
UI : info ( _ ( " Could not save news feed config. " ) )
else
UI : info ( _ ( " News feed config updated successfully. " ) )
end
UI : reset ( )
2017-05-14 08:46:12 +00:00
end
2022-01-21 18:23:21 +00:00
-- This function opens an input dialog that lets the user
-- manually change their feed config. This function is called
-- when there is an error with the parsing.
2018-08-07 19:03:43 +00:00
function NewsDownloader : changeFeedConfig ( )
2021-09-13 19:04:06 +00:00
local feed_config_file = io.open ( self.feed_config_path , " rb " )
2018-08-07 19:03:43 +00:00
local config = feed_config_file : read ( " *all " )
feed_config_file : close ( )
local config_editor
2021-09-13 19:04:06 +00:00
logger.info ( " NewsDownloader: opening configuration file " , self.feed_config_path )
2018-08-07 19:03:43 +00:00
config_editor = InputDialog : new {
2021-09-13 19:04:06 +00:00
title = T ( _ ( " Config: %1 " ) , BD.filepath ( self.feed_config_path ) ) ,
2018-08-07 19:03:43 +00:00
input = config ,
input_type = " string " ,
2019-12-06 21:55:35 +00:00
para_direction_rtl = false , -- force LTR
2018-08-07 19:03:43 +00:00
fullscreen = true ,
condensed = true ,
allow_newline = true ,
cursor_at_end = false ,
add_nav_bar = true ,
reset_callback = function ( )
return config
end ,
save_callback = function ( content )
if content and # content > 0 then
local parse_error = util.checkLuaSyntax ( content )
if not parse_error then
local syntax_okay , syntax_error = pcall ( loadstring ( content ) )
if syntax_okay then
2021-09-13 19:04:06 +00:00
feed_config_file = io.open ( self.feed_config_path , " w " )
2018-08-07 19:03:43 +00:00
feed_config_file : write ( content )
feed_config_file : close ( )
return true , _ ( " Configuration saved " )
else
return false , T ( _ ( " Configuration invalid: %1 " ) , syntax_error )
end
else
2021-09-13 19:04:06 +00:00
return false , T ( _ ( " Configuration invalid: %1 " ) , parse_error )
end
2018-08-07 19:03:43 +00:00
end
return false , _ ( " Configuration empty " )
end ,
}
UIManager : show ( config_editor )
config_editor : onShowKeyboard ( )
end
2022-01-21 18:23:21 +00:00
2021-09-13 19:04:06 +00:00
function NewsDownloader : openDownloadsFolder ( )
local FileManager = require ( " apps/filemanager/filemanager " )
if self.ui . document then
self.ui : onClose ( )
end
if FileManager.instance then
FileManager.instance : reinit ( self.download_dir )
else
FileManager : showFiles ( self.download_dir )
end
end
2018-08-07 19:03:43 +00:00
2017-10-27 21:00:49 +00:00
function NewsDownloader : onCloseDocument ( )
local document_full_path = self.ui . document.file
2021-09-13 19:04:06 +00:00
if document_full_path and self.download_dir and self.download_dir == string.sub ( document_full_path , 1 , string.len ( self.download_dir ) ) then
2017-10-27 21:00:49 +00:00
logger.dbg ( " NewsDownloader: document_full_path: " , document_full_path )
2021-09-13 19:04:06 +00:00
logger.dbg ( " NewsDownloader: self.download_dir: " , self.download_dir )
2017-10-27 21:00:49 +00:00
logger.dbg ( " NewsDownloader: removing NewsDownloader file from history. " )
ReadHistory : removeItemByPath ( document_full_path )
2020-05-19 16:21:58 +00:00
local doc_dir = util.splitFilePathName ( document_full_path )
self.ui : setLastDirForFileBrowser ( doc_dir )
2017-10-27 21:00:49 +00:00
end
end
2017-04-19 15:59:45 +00:00
return NewsDownloader