From ebcefe1c9818a32e72b643e1a5a7fc4054d49a6b Mon Sep 17 00:00:00 2001 From: teroshan <10300015+teroshan@users.noreply.github.com> Date: Sun, 13 Oct 2019 08:48:37 +0200 Subject: [PATCH] [feat] plugins/Wallabag: add ability to set a list of tags to ignore (#5467) A new setting has been adding allowing to set a comma separated list of tags to ignore. Entries with either of these tags will be skipped by the client when fetching the list of articles to download. Extra articles will be fetched from the server to make up for the skipped articles, ensuring to meet the target number of articles. --- plugins/wallabag.koplugin/main.lua | 131 ++++++++++++++++++++++++++++- 1 file changed, 127 insertions(+), 4 deletions(-) diff --git a/plugins/wallabag.koplugin/main.lua b/plugins/wallabag.koplugin/main.lua index aa3f0c238..3ed4e3c03 100644 --- a/plugins/wallabag.koplugin/main.lua +++ b/plugins/wallabag.koplugin/main.lua @@ -45,6 +45,7 @@ function Wallabag:init() self.is_sync_remote_delete = false self.is_archiving_deleted = false self.filter_tag = "" + self.ignore_tags = "" self.articles_per_sync = 30 self.ui.menu:registerToMainMenu(self) @@ -73,6 +74,9 @@ function Wallabag:init() if self.wb_settings.data.wallabag.filter_tag then self.filter_tag = self.wb_settings.data.wallabag.filter_tag end + if self.wb_settings.data.wallabag.ignore_tags then + self.ignore_tags = self.wb_settings.data.wallabag.ignore_tags + end if self.wb_settings.data.wallabag.articles_per_sync ~= nil then self.articles_per_sync = self.wb_settings.data.wallabag.articles_per_sync end @@ -181,6 +185,18 @@ function Wallabag:addToMainMenu(menu_items) self:setFilterTag(touchmenu_instance) end, }, + { + text_func = function() + if not self.ignore_tags or self.ignore_tags == "" then + return _("Ignore tags") + end + return T(_("Ignore tags (%1)"), self.ignore_tags) + end, + keep_menu_open = true, + callback = function(touchmenu_instance) + self:setIgnoreTags(touchmenu_instance) + end, + }, { text = _("Remotely delete finished articles"), checked_func = function() return self.is_delete_finished end, @@ -315,13 +331,88 @@ function Wallabag:getBearerToken() end end +--- Get a JSON formatted list of articles from the server. +-- The list should have self.article_per_sync item, or less if an error occured. +-- If filter_tag is set, only articles containing this tag are queried. +-- If ignore_tags is defined, articles containing either of the tags are skipped. function Wallabag:getArticleList() local filtering = "" if self.filter_tag ~= "" then filtering = "&tags=" .. self.filter_tag end - local articles_url = "/api/entries.json?archive=0&perPage=" .. self.articles_per_sync .. filtering - return self:callAPI("GET", articles_url, nil, "", "") + + local article_list = {} + local page = 1 + -- query the server for articles until we hit our target number + while #article_list < self.articles_per_sync do + -- get the JSON containing the article list + local articles_url = "/api/entries.json?archive=0" + .. "&page=" .. page + .. "&perPage=" .. self.articles_per_sync + .. filtering + local articles_json = self:callAPI("GET", articles_url, nil, "", "") + + if not articles_json then + -- we may have hit the last page, there are no more articles + logger.dbg("Wallabag: couldn't get page #", page) + break -- exit while loop + end + + -- We're only interested in the actual articles in the JSON + -- build an array of those so it's easier to manipulate later + local new_article_list = {} + for _, article in ipairs(articles_json._embedded.items) do + table.insert(new_article_list, article) + end + + -- Apply the filters + new_article_list = self:filterIgnoredTags(new_article_list) + + -- Append the filtered list to the final article list + for i, article in ipairs(new_article_list) do + if #article_list == self.articles_per_sync then + logger.dbg("Wallabag: hit the article target", self.articles_per_sync) + break + end + table.insert(article_list, article) + end + + page = page + 1 + end + + return article_list +end + +--- Remove all the articles from the list containing one of the ignored tags. +-- article_list: array containing a json formatted list of articles +-- returns: same array, but without any articles that contain an ignored tag. +function Wallabag:filterIgnoredTags(article_list) + -- decode all tags to ignore + local ignoring = {} + if self.ignore_tags ~= "" then + for tag in util.gsplit(self.ignore_tags, "[,]+", false) do + ignoring[tag] = true + end + end + + -- rebuild a list without the ignored articles + local filtered_list = {} + for _, article in ipairs(article_list) do + local skip_article = false + for _, tag in ipairs(article.tags) do + if ignoring[tag.label] then + skip_article = true + logger.dbg("Wallabag: ignoring tag", tag.label, "in article", + article.id, ":", article.title) + break -- no need to look for other tags + end + end + if not skip_article then + table.insert(filtered_list, article) + end + end + + return filtered_list end --- Download Wallabag article. @@ -480,13 +571,13 @@ function Wallabag:synchronize() if self.access_token ~= "" then local articles = self:getArticleList() if articles then - logger.dbg("Wallabag: number of articles: ", articles.total) + logger.dbg("Wallabag: number of articles: ", #articles) info = InfoMessage:new{ text = _("Downloading articles…") } UIManager:show(info) UIManager:forceRePaint() UIManager:close(info) - for _, article in ipairs(articles._embedded.items) do + for _, article in ipairs(articles) do logger.dbg("Wallabag: processing article ID: ", article.id) remote_article_ids[ tostring(article.id) ] = true local res = self:download(article) @@ -695,6 +786,37 @@ function Wallabag:setFilterTag(touchmenu_instance) self.tag_dialog:onShowKeyboard() end +function Wallabag:setIgnoreTags(touchmenu_instance) + self.ignore_tags_dialog = InputDialog:new { + title = _("Tags to ignore"), + description = _("Enter a comma-separated list of tags to ignore."), + input = self.ignore_tags, + input_type = "string", + buttons = { + { + { + text = _("Cancel"), + callback = function() + UIManager:close(self.ignore_tags_dialog) + end, + }, + { + text = _("Set tags"), + is_enter_default = true, + callback = function() + self.ignore_tags = self.ignore_tags_dialog:getInputText() + self:saveSettings() + touchmenu_instance:updateItems() + UIManager:close(self.ignore_tags_dialog) + end, + } + } + }, + } + UIManager:show(self.ignore_tags_dialog) + self.ignore_tags_dialog:onShowKeyboard() +end + function Wallabag:editServerSettings() local text_info = T(_([[ Enter the details of your Wallabag server and account. @@ -836,6 +958,7 @@ function Wallabag:saveSettings() password = self.password, directory = self.directory, filter_tag = self.filter_tag, + ignore_tags = self.ignore_tags, is_delete_finished = self.is_delete_finished, is_delete_read = self.is_delete_read, is_archiving_deleted = self.is_archiving_deleted,