Added RSS feed to each category
authorHarishankar <v.harishankar@gmail.com>
Fri, 22 May 2020 11:37:12 +0000 (17:07 +0530)
committerHarishankar <v.harishankar@gmail.com>
Fri, 22 May 2020 11:37:12 +0000 (17:07 +0530)
Added RSS feed to each category in the document tree

biawebdocumenttree.hpp
biawebrss.hpp [new file with mode: 0644]
biawebstrings.hpp
biawebtemplate.hpp
templates/rss.tpl.xml [new file with mode: 0644]
templates/rssitem.tpl.xml [new file with mode: 0644]
templates/stringbits.txt

index 70471f3..447a5c7 100644 (file)
@@ -12,6 +12,7 @@
 #include "biawebutil.hpp"
 #include "biawebdoclist.hpp"
 #include "biawebtemplate.hpp"
+#include "biawebrss.hpp"
 
 // class to implement a document tree - both with or without subtrees
 namespace biaweb {
@@ -196,8 +197,7 @@ namespace biaweb {
             item1.set_item_url (this->stub_hierarchy() + "index.html");
             bar1.get()->add_sidebar_item (item1);
         }
-        index.get()->add_side_bar (*bar1.get());
-
         // create a sidebar for the child levels if there are children
         std::unique_ptr<SideBar> bar2 (new SideBar ());
         bar2.get()->set_title (tpl->get_stringbit (SUB_CAT) + this->title);
@@ -209,7 +209,6 @@ namespace biaweb {
                                             tree.stub + "/" + "index.html");
             bar2.get()->add_sidebar_item (item);
         }
-        index.get()->add_side_bar (*bar2.get());
 
         // create the path and then the index file
         std::filesystem::create_directories (filepath);
@@ -235,7 +234,20 @@ namespace biaweb {
             par1 = par1->parent;
         }
 
+        // rss feed
+        std::unique_ptr<RSSFeed> feed (new RSSFeed ());
+        feed.get()->set_pub_date (index.get()->get_creation_date());
+
+        // iterate through the documents and generate the document
         for (Document doc : this->docs) {
+            // Add the document to RSS feed
+            RSSFeedItem fitem (doc.get_title(), doc.get_meta_desc (),
+                        urlpath + doc.get_filename() + ".html", 
+                        doc.get_creation_date());
+            // If the items don't exceed max size of RSS feed
+            if (feed.get()->get_num_items() <= MAX_RSS_FEED)
+                feed.get()->add_rss_item (fitem);                        
+            // Add the document to the document list
             DocListItem item (doc.get_title(),
                             urlpath + doc.get_filename() + ".html", 
                             doc.get_creation_date(), doc.get_modified_date (), 
@@ -249,6 +261,23 @@ namespace biaweb {
             doc.output_to_html (tpl, filepath);
         }
 
+        // output the rss feed 
+        feed.get()->output_to_html (tpl, filepath);
+
+        // add the side bars
+        index.get()->add_side_bar (*bar1.get());
+        index.get()->add_side_bar (*bar2.get());
+
+        // sidebar for RSS feed
+        // if there are are items in the feed add the link
+        if (feed.get()->get_num_items () > 0) {
+            std::unique_ptr<SideBar> bar3 (new SideBar ());
+            bar3.get()->set_title (tpl->get_stringbit (SUBSCRIBE));
+            bar3.get()->add_sidebar_item (
+                    GenericLinkItem (tpl->get_stringbit(RSS_FEED), urlpath + "/feed.xml"));
+            index.get()->add_side_bar (*bar3.get());
+        }
+
         // add the navigation bit
         index.get()->set_navigation_bit (*navbit.get());
         // index should contain the summary followed by the article list
diff --git a/biawebrss.hpp b/biawebrss.hpp
new file mode 100644 (file)
index 0000000..eb4d0aa
--- /dev/null
@@ -0,0 +1,115 @@
+#ifndef __BIAWEBRSSFEED__
+#define __BIAWEBRSSFEED__
+
+#include "biawebutil.hpp"
+#include "biawebtemplate.hpp"
+#include <ctime>
+#include <list>
+#include "fmt/format.h"
+
+namespace biaweb {
+    // class to define and implement an RSS feed item
+    class RSSFeedItem {
+      protected:
+        std::string title;
+        std::string description;
+        std::string url;
+        std::time_t pub_date;
+      public:
+        // Main Constructor
+        RSSFeedItem (std::string title, std::string desc, 
+                        std::string url, std::time_t pub) {
+            this->title = escape_html (title);
+            this->description = escape_html (desc);
+            this->url = url;
+            this->pub_date = pub;
+        }
+
+        // generate HTML using specified template
+        std::string to_html (Template *t);
+
+        std::string get_title() {
+               return this->title;
+        }
+        void set_title(std::string title) {
+               this->title =  escape_html (title);
+        }
+        std::string get_description() {
+               return this->description;
+        }
+        void set_description(std::string description) {
+               this->description = escape_html (description);
+        }
+        std::string get_url() {
+               return this->url;
+        }
+        void set_url(std::string url) {
+               this->url = url;
+        }
+        std::time_t get_pub_date() {
+               return this->pub_date;
+        }
+        void set_pub_date(std::time_t pub_date) {
+               this->pub_date = pub_date;
+        }
+    };
+    std::string RSSFeedItem::to_html (Template *t) {
+        std::string item_tpl = t->get_rss_item_tpl ();
+
+        std::tm ct = *std::localtime (&this->pub_date);
+
+        std::string output = fmt::format (item_tpl, 
+                                            fmt::arg ("title", this->title),
+                                            fmt::arg ("description", this->description),
+                                            fmt::arg ("url", this->url),
+                                            fmt::arg ("pubdate", ct));
+        return output;
+    }
+
+    // class to implement an RSS feed
+    class RSSFeed {
+      protected:
+        std::time_t pub_date;
+        std::list<RSSFeedItem> items;
+      public:
+        // add a feed item 
+        void add_rss_item (RSSFeedItem item) {
+            this->items.insert (items.cend(), item);
+        }
+
+        // number of items
+        std::size_t get_num_items () {
+            return this->items.size ();
+        } 
+
+        std::time_t get_pub_date() {
+               return this->pub_date;
+        }
+        void set_pub_date(std::time_t pub_date) {
+               this->pub_date = pub_date;
+        }
+
+        // output the RSS feed file as feed.xml
+        void output_to_html (Template *t, std::string path) {
+            std::string templ_str = t->get_rss_tpl ();
+            // only if there are feed items, output the feed.xml file
+            if (this->items.size () != 0) {
+                std::string items_str ;
+                // get the items 
+                for (auto item : this->items) 
+                    items_str += item.to_html (t);
+                
+                std::tm ct = *std::localtime (&this->pub_date);
+
+                std::string output = fmt::format (templ_str, 
+                                            fmt::arg ("pubdate", ct),
+                                            fmt::arg ("items", items_str) );
+                std::ofstream f (path + "/feed.xml");
+                f << output;
+                f.close ();
+            }
+        }
+    };
+}
+
+#endif 
\ No newline at end of file
index a421ee2..fb79a6a 100644 (file)
@@ -17,6 +17,9 @@ namespace biaweb {
 \t<templatedir> - directory containing the templates\n \
 NOTE: directory argument need not terminate with the separator (/)";
 
+    // MAXIMUM SIZE OF RSS FEED
+    const unsigned int MAX_RSS_FEED = 10;
+
     // NAMED INDEX FOR DOCUMENT STRING BITS (LOADED FROM TEMPLATE FILE stringbits.txt)
     const unsigned int HOME = 0;
     const unsigned int ARTICLES_LIST = 1;
@@ -24,6 +27,9 @@ NOTE: directory argument need not terminate with the separator (/)";
     const unsigned int NAVIGATION = 3;
     const unsigned int SUB_CAT = 4;
     const unsigned int GO_UP = 5;
+    const unsigned int SUBSCRIBE = 6;
+    const unsigned int RSS_FEED = 7;
+
 }
 
 #endif
index 604cb26..8dd39df 100644 (file)
@@ -19,7 +19,9 @@ namespace biaweb {
         std::string navigationbit_tpl;
         std::string sidebar_tpl;
         std::string style_tpl;
-        std::array<std::string, 6> stringbits;
+        std::string rss_tpl;
+        std::string rss_item_tpl;
+        std::array<std::string, 8> stringbits;
       public:
         // constructor: generate the template bits from a template directory 
         Template (std::string templatedir) ;
@@ -34,6 +36,8 @@ namespace biaweb {
         std::string get_sidebar_tpl () { return this->sidebar_tpl; }
         std::string get_style_tpl () { return this->style_tpl; } 
         std::string get_stringbit (unsigned int id) { return this->stringbits[id]; }
+        std::string get_rss_tpl () { return this->rss_tpl; }
+        std::string get_rss_item_tpl () { return this->rss_item_tpl; }
     };
 
     // construct a template from a source directory
@@ -48,7 +52,8 @@ namespace biaweb {
         this->navigationbit_tpl = load_from_file (templatedir + "/navigationbit.tpl.html");
         this->sidebar_tpl = load_from_file (templatedir + "/sidebar.tpl.html");
         this->style_tpl = load_from_file (templatedir + "/style.tpl.css");
-
+        this->rss_tpl = load_from_file (templatedir + "/rss.tpl.xml");
+        this->rss_item_tpl = load_from_file (templatedir + "/rssitem.tpl.xml");
 
         // read the stringbits into the array
         std::ifstream f (templatedir + "/stringbits.txt");
diff --git a/templates/rss.tpl.xml b/templates/rss.tpl.xml
new file mode 100644 (file)
index 0000000..d3d49ed
--- /dev/null
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<rss version="2.0">
+<channel>
+    <!-- change title description and link as needed-->
+    <title>My Site</title>
+    <description>Site Description</description>
+    <link>http://my.site</link>
+    <pubDate>{pubdate:%a, %d %b %Y %H:%M:%S %z}</pubDate>
+    {items}
+</channel>
+</rss>
\ No newline at end of file
diff --git a/templates/rssitem.tpl.xml b/templates/rssitem.tpl.xml
new file mode 100644 (file)
index 0000000..b7bdfa1
--- /dev/null
@@ -0,0 +1,9 @@
+    <item>
+    <title>{title}</title>
+    <description>{description}</description>
+    <!-- change http://my.site to your actual site URL -->
+    <!-- don't touch anything within the curly braces-->
+    <link>http://my.site/{url}</link>
+    <guid isPermaLink="false">http://my.site/{url}</guid>
+    <pubDate>{pubdate:%a, %d %b %Y %H:%M:%S %z}</pubDate>
+    </item>
\ No newline at end of file
index 70341af..774a7e0 100644 (file)
@@ -3,4 +3,6 @@ List of Articles
 Index Page
 Navigation
 Sub categories: 
-Go up
\ No newline at end of file
+Go up
+Subscribe
+RSS Feed
\ No newline at end of file