1 #ifndef NEWSBOAT_RSSFEED_H_ 2 #define NEWSBOAT_RSSFEED_H_ 3 4 #include <memory> 5 #include <mutex> 6 #include <string> 7 #include <unordered_map> 8 #include <vector> 9 10 #include "matchable.h" 11 #include "rssitem.h" 12 #include "utils.h" 13 14 namespace newsboat { 15 16 enum class DlStatus { SUCCESS, TO_BE_DOWNLOADED, DURING_DOWNLOAD, DL_ERROR }; 17 18 class Cache; 19 20 class RssFeed : public Matchable { 21 public: 22 explicit RssFeed(Cache* c); 23 RssFeed(); 24 ~RssFeed() override; title_raw()25 std::string title_raw() const 26 { 27 return title_; 28 } 29 std::string title() const; set_title(const std::string & t)30 void set_title(const std::string& t) 31 { 32 title_ = t; 33 utils::trim(title_); 34 } 35 description()36 std::string description() const 37 { 38 return description_; 39 } set_description(const std::string & d)40 void set_description(const std::string& d) 41 { 42 description_ = d; 43 } 44 link()45 const std::string& link() const 46 { 47 return link_; 48 } set_link(const std::string & l)49 void set_link(const std::string& l) 50 { 51 link_ = l; 52 } 53 pubDate()54 std::string pubDate() const 55 { 56 return utils::mt_strf_localtime(_("%a, %d %b %Y %T %z"), pubDate_); 57 } set_pubDate(time_t t)58 void set_pubDate(time_t t) 59 { 60 pubDate_ = t; 61 } 62 63 bool hidden() const; 64 items()65 std::vector<std::shared_ptr<RssItem>>& items() 66 { 67 return items_; 68 } add_item(std::shared_ptr<RssItem> item)69 void add_item(std::shared_ptr<RssItem> item) 70 { 71 items_.push_back(item); 72 items_guid_map[item->guid()] = item; 73 } add_items(const std::vector<std::shared_ptr<RssItem>> & items)74 void add_items(const std::vector<std::shared_ptr<RssItem>>& items) 75 { 76 for (const auto& item : items) { 77 items_.push_back(item); 78 items_guid_map[item->guid()] = item; 79 } 80 } set_items(std::vector<std::shared_ptr<RssItem>> & items)81 void set_items(std::vector<std::shared_ptr<RssItem>>& items) 82 { 83 erase_items(items_.begin(), items_.end()); 84 add_items(items); 85 } 86 erase_items(std::vector<std::shared_ptr<RssItem>>::iterator begin,std::vector<std::shared_ptr<RssItem>>::iterator end)87 void erase_items(std::vector<std::shared_ptr<RssItem>>::iterator begin, 88 std::vector<std::shared_ptr<RssItem>>::iterator end) 89 { 90 for (auto it = begin; it != end; ++it) { 91 items_guid_map.erase((*it)->guid()); 92 } 93 items_.erase(begin, end); 94 } erase_item(std::vector<std::shared_ptr<RssItem>>::iterator pos)95 void erase_item(std::vector<std::shared_ptr<RssItem>>::iterator pos) 96 { 97 items_guid_map.erase((*pos)->guid()); 98 items_.erase(pos); 99 } 100 101 std::shared_ptr<RssItem> get_item_by_guid(const std::string& guid); 102 std::shared_ptr<RssItem> get_item_by_guid_unlocked( 103 const std::string& guid); 104 105 /// \brief User-specified feed URL. Can't be empty, otherwise we wouldn't 106 /// be able to fetch the feed. rssurl()107 const std::string& rssurl() const 108 { 109 return rssurl_; 110 } 111 void set_rssurl(const std::string& u); 112 113 unsigned int unread_item_count() const; total_item_count()114 unsigned int total_item_count() const 115 { 116 return items_.size(); 117 } 118 119 void set_tags(const std::vector<std::string>& tags); 120 bool matches_tag(const std::string& tag); 121 std::string get_tags() const; 122 std::string get_firsttag(); 123 124 nonstd::optional<std::string> attribute_value(const std::string& attr) const 125 override; 126 127 void update_items(std::vector<std::shared_ptr<RssFeed>> feeds); 128 set_query(const std::string & s)129 void set_query(const std::string& s) 130 { 131 query = s; 132 } 133 is_query_feed()134 bool is_query_feed() const 135 { 136 return rssurl_.substr(0, 6) == "query:"; 137 } 138 is_search_feed()139 bool is_search_feed() const 140 { 141 return search_feed; 142 } 143 set_search_feed(bool b)144 void set_search_feed(bool b) 145 { 146 search_feed = b; 147 } 148 149 void sort(const ArticleSortStrategy& sort_strategy); 150 void sort_unlocked(const ArticleSortStrategy& sort_strategy); 151 152 void purge_deleted_items(); 153 set_rtl(bool b)154 void set_rtl(bool b) 155 { 156 is_rtl_ = b; 157 } is_rtl()158 bool is_rtl() 159 { 160 return is_rtl_; 161 } 162 set_index(unsigned int i)163 void set_index(unsigned int i) 164 { 165 idx = i; 166 } get_index()167 unsigned int get_index() 168 { 169 return idx; 170 } 171 set_order(unsigned int x)172 void set_order(unsigned int x) 173 { 174 order = x; 175 } get_order()176 unsigned int get_order() 177 { 178 return order; 179 } 180 181 void set_feedptrs(std::shared_ptr<RssFeed> self); 182 183 std::string get_status(); 184 reset_status()185 void reset_status() 186 { 187 std::lock_guard<std::mutex> guard(status_mutex_); 188 status_ = DlStatus::TO_BE_DOWNLOADED; 189 } set_status(DlStatus st)190 void set_status(DlStatus st) 191 { 192 std::lock_guard<std::mutex> guard(status_mutex_); 193 status_ = st; 194 } 195 196 void unload(); 197 void load(); 198 199 void mark_all_items_read(); 200 201 // this is ugly, but makes it possible to lock items use e.g. from the Cache class 202 mutable std::mutex item_mutex; 203 204 private: 205 std::string title_; 206 std::string description_; 207 std::string link_; 208 time_t pubDate_; 209 std::string rssurl_; 210 std::vector<std::shared_ptr<RssItem>> items_; 211 std::unordered_map<std::string, std::shared_ptr<RssItem>> 212 items_guid_map; 213 std::vector<std::string> tags_; 214 std::string query; 215 216 Cache* ch; 217 218 bool search_feed; 219 bool is_rtl_; 220 unsigned int idx; 221 unsigned int order; 222 std::mutex items_guid_map_mutex; 223 224 DlStatus status_; 225 std::mutex status_mutex_; 226 }; 227 228 } // namespace newsboat 229 230 #endif /* NEWSBOAT_RSSFEED_H_ */ 231