From fd2a3391adb73b19f7501854f0b44aff8d5e853b Mon Sep 17 00:00:00 2001
From: Bob Mottram <bob@freedombone.net>
Date: Tue, 13 Oct 2020 17:58:45 +0100
Subject: [PATCH] Rss feed for all blogs on the instance

---
 blog.py         | 13 +++++--
 daemon.py       | 94 +++++++++++++++++++++++++++++++++++++++++++------
 webinterface.py | 11 ++++--
 3 files changed, 102 insertions(+), 16 deletions(-)

diff --git a/blog.py b/blog.py
index 4e474abe..5d1019ef 100644
--- a/blog.py
+++ b/blog.py
@@ -478,7 +478,8 @@ def htmlBlogPage(authorized: bool, session,
 def htmlBlogPageRSS2(authorized: bool, session,
                      baseDir: str, httpPrefix: str, translate: {},
                      nickname: str, domain: str, port: int,
-                     noOfItems: int, pageNumber: int) -> str:
+                     noOfItems: int, pageNumber: int,
+                     includeHeader: bool) -> str:
     """Returns an RSS version 2 feed containing posts
     """
     if ' ' in nickname or '@' in nickname or \
@@ -490,7 +491,10 @@ def htmlBlogPageRSS2(authorized: bool, session,
         if port != 80 and port != 443:
             domainFull = domain + ':' + str(port)
 
-    blogRSS2 = rss2Header(httpPrefix, nickname, domainFull, 'Blog', translate)
+    blogRSS2 = ''
+    if includeHeader:
+        blogRSS2 = rss2Header(httpPrefix, nickname, domainFull,
+                              'Blog', translate)
 
     blogsIndex = baseDir + '/accounts/' + \
         nickname + '@' + domain + '/tlblogs.index'
@@ -504,7 +508,10 @@ def htmlBlogPageRSS2(authorized: bool, session,
                                        pageNumber)
 
     if not timelineJson:
-        return blogRSS2 + rss2Footer()
+        if includeHeader:
+            return blogRSS2 + rss2Footer()
+        else:
+            return blogRSS2
 
     if pageNumber is not None:
         for item in timelineJson['orderedItems']:
diff --git a/daemon.py b/daemon.py
index b773e5a5..b93bb4ff 100644
--- a/daemon.py
+++ b/daemon.py
@@ -213,6 +213,8 @@ from devices import E2EEdevicesCollection
 from devices import E2EEvalidDevice
 from devices import E2EEaddDevice
 from newswire import getRSSfromDict
+from newswire import rss2Header
+from newswire import rss2Footer
 from newsdaemon import runNewswireWatchdog
 from newsdaemon import runNewswireDaemon
 import os
@@ -4228,7 +4230,8 @@ class PubServer(BaseHTTPRequestHandler):
                                      nickname,
                                      domain,
                                      port,
-                                     maxPostsInRSSFeed, 1)
+                                     maxPostsInRSSFeed, 1,
+                                     True)
                 if msg is not None:
                     msg = msg.encode('utf-8')
                     self._set_headers('text/xml', len(msg),
@@ -4246,6 +4249,66 @@ class PubServer(BaseHTTPRequestHandler):
                   path + ' ' + callingDomain)
         self._404()
 
+    def _getRSS2site(self, authorized: bool,
+                     callingDomain: str, path: str,
+                     baseDir: str, httpPrefix: str,
+                     domainFull: str, port: int, proxyType: str,
+                     translate: {},
+                     GETstartTime, GETtimings: {},
+                     debug: bool):
+        """Returns an RSS2 feed for all blogs on this instance
+        """
+        if not self.server.session:
+            print('Starting new session during RSS request')
+            self.server.session = \
+                createSession(proxyType)
+            if not self.server.session:
+                print('ERROR: GET failed to create session ' +
+                      'during RSS request')
+                self._404()
+                return
+
+        msg = ''
+        for subdir, dirs, files in os.walk(baseDir + '/accounts'):
+            for acct in dirs:
+                if '@' not in acct:
+                    continue
+                if 'inbox@' in acct or 'news@' in acct:
+                    continue
+                nickname = acct.split('@')[0]
+                domain = acct.split('@')[1]
+                msg += \
+                    htmlBlogPageRSS2(authorized,
+                                     self.server.session,
+                                     baseDir,
+                                     httpPrefix,
+                                     self.server.translate,
+                                     nickname,
+                                     domain,
+                                     port,
+                                     maxPostsInRSSFeed, 1,
+                                     False)
+        if msg:
+            msg = rss2Header(httpPrefix,
+                             'news', domainFull,
+                             'News', translate) + msg + rss2Footer()
+
+            msg = msg.encode('utf-8')
+            self._set_headers('text/xml', len(msg),
+                              None, callingDomain)
+            self._write(msg)
+            if debug:
+                print('Sent rss2 feed: ' +
+                      path + ' ' + callingDomain)
+            self._benchmarkGETtimings(GETstartTime, GETtimings,
+                                      'sharedInbox enabled',
+                                      'blog rss2')
+            return
+        if debug:
+            print('Failed to get rss2 feed: ' +
+                  path + ' ' + callingDomain)
+        self._404()
+
     def _getNewswireFeed(self, authorized: bool,
                          callingDomain: str, path: str,
                          baseDir: str, httpPrefix: str,
@@ -8513,15 +8576,26 @@ class PubServer(BaseHTTPRequestHandler):
         # RSS 2.0
         if self.path.startswith('/blog/') and \
            self.path.endswith('/rss.xml'):
-            self._getRSS2feed(authorized,
-                              callingDomain, self.path,
-                              self.server.baseDir,
-                              self.server.httpPrefix,
-                              self.server.domain,
-                              self.server.port,
-                              self.server.proxyType,
-                              GETstartTime, GETtimings,
-                              self.server.debug)
+            if not self.path == '/blog/rss.xml':
+                self._getRSS2feed(authorized,
+                                  callingDomain, self.path,
+                                  self.server.baseDir,
+                                  self.server.httpPrefix,
+                                  self.server.domain,
+                                  self.server.port,
+                                  self.server.proxyType,
+                                  GETstartTime, GETtimings,
+                                  self.server.debug)
+            else:
+                self._getRSS2site(authorized,
+                                  callingDomain, self.path,
+                                  self.server.baseDir,
+                                  self.server.httpPrefix,
+                                  self.server.domain,
+                                  self.server.port,
+                                  self.server.proxyType,
+                                  GETstartTime, GETtimings,
+                                  self.server.debug)
             return
 
         self._benchmarkGETtimings(GETstartTime, GETtimings,
diff --git a/webinterface.py b/webinterface.py
index e91e454a..bb3b7c4b 100644
--- a/webinterface.py
+++ b/webinterface.py
@@ -5508,10 +5508,15 @@ def getLeftColumnContent(baseDir: str, nickname: str, domainFull: str,
             iconsDir + '/edit.png" /></a>\n'
 
     # RSS icon
+    if nickname != 'news':
+        # rss feed for this account
+        rssUrl = httpPrefix + '://' + domainFull + \
+            '/blog/' + nickname + '/rss.xml'
+    else:
+        # rss feed for all accounts on the instance
+        rssUrl = httpPrefix + '://' + domainFull + '/blog/rss.xml'
     htmlStr += \
-        '      <a href="' + \
-        httpPrefix + '://' + domainFull + \
-        '/blog/' + nickname + '/rss.xml">' + \
+        '      <a href="' + rssUrl + '">' + \
         '<img class="' + editImageClass + \
         '" loading="lazy" alt="' + \
         translate['RSS feed for this site'] + \