diff --git a/blog.py b/blog.py index f99039e2..d1097636 100644 --- a/blog.py +++ b/blog.py @@ -247,6 +247,27 @@ def htmlBlogPostContent(authorized: bool, \ return blogStr +def htmlBlogPostRSS(authorized: bool, \ + baseDir: str,httpPrefix: str,translate: {}, \ + nickname: str,domain: str,domainFull: str, \ + postJsonObject: {}, \ + handle: str,restrictToDomain: bool) -> str: + """Returns the RSS feed for a single blog post + """ + messageLink='' + if postJsonObject['object'].get('id'): + messageLink=postJsonObject['object']['id'].replace('/statuses/','/') + if not restrictToDomain or \ + (restrictToDomain and '/'+domain in messageLink): + if postJsonObject['object'].get('summary'): + titleStr=postJsonObject['object']['summary'] + rssStr= ' ' + rssStr+=' '+titleStr+'' + rssStr+=' '+messageLink+'' + rssStr+=' ' + return rssStr + + def htmlBlogPost(authorized: bool, \ baseDir: str,httpPrefix: str,translate: {}, \ nickname: str,domain: str,domainFull: str, \ @@ -307,6 +328,7 @@ def htmlBlogPage(authorized: bool, session, \ if port!=80 and port!=443: domainFull=domain+':'+str(port) + # show previous and next buttons if pageNumber!=None: iconsDir=getIconsDir(baseDir) navigateStr='

' @@ -326,7 +348,13 @@ def htmlBlogPage(authorized: bool, session, \ '/prev.png" class="buttonnext"/>\n' navigateStr+='

' blogStr+=navigateStr - + + # show rss link + blogStr+='

' + blogStr+='' + blogStr+='RSS' + blogStr+='

' + for item in timelineJson['orderedItems']: if item['type']!='Create': continue @@ -342,6 +370,60 @@ def htmlBlogPage(authorized: bool, session, \ return blogStr+htmlFooter() return None +def rssHeader(httpPrefix: str,nickname: str,domainFull: str,translate: {}) -> str: + rssStr="" + rssStr+="" + rssStr+='' + rssStr+=' '+translate['Blog']+'' + rssStr+=' '+httpPrefix+'://'+domainFull+'/users/'+nickname+'/rss.xml'+'' + return rssStr + +def rssFooter() -> str: + rssStr='' + rssStr+='' + return rssStr + +def htmlBlogPageRSS(authorized: bool, session, \ + baseDir: str,httpPrefix: str,translate: {}, \ + nickname: str,domain: str,port: int, \ + noOfItems: int,pageNumber: int) -> str: + """Returns an rss feed containing posts + """ + if ' ' in nickname or '@' in nickname or '\n' in nickname: + return None + + domainFull=domain + if port: + if port!=80 and port!=443: + domainFull=domain+':'+str(port) + + blogRSS=rssHeader(httpPrefix,nickname,domainFull,translate) + + blogsIndex= \ + baseDir+'/accounts/'+nickname+'@'+domain+'/tlblogs.index' + if not os.path.isfile(blogsIndex): + return blogRSS+rssFooter() + + timelineJson= \ + createBlogsTimeline(session,baseDir, \ + nickname,domain,port,httpPrefix, \ + noOfItems,False,False,pageNumber) + + if not timelineJson: + return blogRSS+rssFooter() + + if pageNumber!=None: + for item in timelineJson['orderedItems']: + if item['type']!='Create': + continue + + blogRSS+= \ + htmlBlogPostRSS(authorized,baseDir,httpPrefix,translate, \ + nickname,domain,domainFull,item, \ + None,True) + + return blogRSS+rssFooter() + def getBlogIndexesForAccounts(baseDir: str) -> {}: """ Get the index files for blogs for each account diff --git a/daemon.py b/daemon.py index b472cc8d..e0343d80 100644 --- a/daemon.py +++ b/daemon.py @@ -110,6 +110,7 @@ from roles import setRole from roles import clearModeratorStatus from skills import outboxSkills from availability import outboxAvailability +from blog import htmlBlogPageRSS from blog import htmlBlogView from blog import htmlBlogPage from blog import htmlBlogPost @@ -196,6 +197,9 @@ maxPostsInMediaFeed=6 # Blogs can be longer, so don't show many per page maxPostsInBlogsFeed=4 +# Maximum number of entries in returned rss.xml +maxPostsInRSSFeed=10 + # number of follows/followers per page followsPerPage=12 @@ -999,6 +1003,34 @@ class PubServer(BaseHTTPRequestHandler): self._benchmarkGETtimings(GETstartTime,GETtimings,8) + if self.path.startswith('/blog/') and self.path.endswith('/rss.xml'): + nickname=self.path.split('/blog/')[1] + if '/' not in nickname: + if not nickname.startswith('rss.'): + if os.path.isdir(self.server.baseDir+ \ + '/accounts/'+nickname+ \ + '@'+self.server.domain): + if not self.server.session: + self.server.session= \ + createSession(self.server.useTor) + msg= \ + htmlBlogPageRSS(authorized, \ + self.server.session, \ + self.server.baseDir, \ + self.server.httpPrefix, \ + self.server.translate, \ + nickname, \ + self.server.domain, \ + self.server.port, \ + maxPostsInRSSFeed,1) + if msg!=None: + msg=msg.encode() + self._set_headers('application/rss+xml',len(msg),cookie) + self._write(msg) + return + self._404() + return + # show the main blog page if htmlGET and (self.path=='/blog' or \ self.path=='/blog/' or \ diff --git a/epicyon-profile.css b/epicyon-profile.css index 0f2b6573..6efd1838 100644 --- a/epicyon-profile.css +++ b/epicyon-profile.css @@ -90,6 +90,10 @@ a:link { position: relative; } +.rssfeed img { + width: 5%; +} + .ssbaddr { font-size: var(--font-size5); } diff --git a/img/icons/hacker/rss.png b/img/icons/hacker/rss.png new file mode 100644 index 00000000..bbaf9d20 Binary files /dev/null and b/img/icons/hacker/rss.png differ diff --git a/img/icons/light/rss.png b/img/icons/light/rss.png new file mode 100644 index 00000000..bbaf9d20 Binary files /dev/null and b/img/icons/light/rss.png differ diff --git a/img/icons/purple/rss.png b/img/icons/purple/rss.png new file mode 100644 index 00000000..bbaf9d20 Binary files /dev/null and b/img/icons/purple/rss.png differ diff --git a/img/icons/rss.png b/img/icons/rss.png new file mode 100644 index 00000000..bbaf9d20 Binary files /dev/null and b/img/icons/rss.png differ