#ifndef NEWSBOAT_RSSFEED_H_ #define NEWSBOAT_RSSFEED_H_ #include #include #include #include #include #include "config.h" #include "matchable.h" #include "rssitem.h" #include "utils.h" namespace newsboat { enum class DlStatus { SUCCESS, TO_BE_DOWNLOADED, DURING_DOWNLOAD, DL_ERROR }; class Cache; class RssFeed : public Matchable { public: explicit RssFeed(Cache* c, const std::string& rssurl); ~RssFeed() override; std::string title_raw() const { return title_; } std::string title() const; void set_title(const std::string& t) { title_ = t; utils::trim(title_); } std::string description() const { return description_; } void set_description(const std::string& d) { description_ = d; } /// \brief Feed's canonical URL. Empty if feed was never fetched. const std::string& link() const { return link_; } void set_link(const std::string& l) { link_ = l; } std::string pubDate() const { return utils::mt_strf_localtime(_("%a, %d %b %Y %T %z"), pubDate_); } void set_pubDate(time_t t) { pubDate_ = t; } bool hidden() const; std::vector>& items() { return items_; } void add_item(std::shared_ptr item) { items_.push_back(item); items_guid_map[item->guid()] = item; } void add_items(const std::vector>& items) { for (const auto& item : items) { items_.push_back(item); items_guid_map[item->guid()] = item; } } void set_items(std::vector>& items) { erase_items(items_.begin(), items_.end()); add_items(items); } void erase_items(std::vector>::iterator begin, std::vector>::iterator end) { for (auto it = begin; it != end; ++it) { items_guid_map.erase((*it)->guid()); } items_.erase(begin, end); } void erase_item(std::vector>::iterator pos) { items_guid_map.erase((*pos)->guid()); items_.erase(pos); } std::shared_ptr get_item_by_guid(const std::string& guid); std::shared_ptr get_item_by_guid_unlocked( const std::string& guid); /// \brief User-specified feed URL. const std::string& rssurl() const { return rssurl_; } unsigned int unread_item_count() const; unsigned int total_item_count() const { return items_.size(); } void set_tags(const std::vector& tags); bool matches_tag(const std::string& tag); std::vector get_tags() const; std::string get_firsttag(); nonstd::optional attribute_value(const std::string& attr) const override; void update_items(std::vector> feeds); bool is_query_feed() const { return rssurl_.substr(0, 6) == "query:"; } bool is_search_feed() const { return search_feed; } void set_search_feed(bool b) { search_feed = b; } void sort(const ArticleSortStrategy& sort_strategy); void sort_unlocked(const ArticleSortStrategy& sort_strategy); void purge_deleted_items(); void set_rtl(bool b) { is_rtl_ = b; } bool is_rtl() { return is_rtl_; } void set_index(unsigned int i) { idx = i; } void set_order(unsigned int x) { order = x; } unsigned int get_order() { return order; } void set_feedptrs(std::shared_ptr self); std::string get_status(); void reset_status() { std::lock_guard guard(status_mutex_); status_ = DlStatus::TO_BE_DOWNLOADED; } void set_status(DlStatus st) { std::lock_guard guard(status_mutex_); status_ = st; } void unload(); void load(); void mark_all_items_read(); // this is ugly, but makes it possible to lock items use e.g. from the Cache class mutable std::mutex item_mutex; private: std::string title_; std::string description_; std::string link_; time_t pubDate_; const std::string rssurl_; std::vector> items_; std::unordered_map> items_guid_map; std::vector tags_; std::string query; Cache* ch; bool search_feed; bool is_rtl_; unsigned int idx; unsigned int order; std::mutex items_guid_map_mutex; DlStatus status_; std::mutex status_mutex_; }; } // namespace newsboat #endif /* NEWSBOAT_RSSFEED_H_ */