Skip to content

Commit

Permalink
more misc rss
Browse files Browse the repository at this point in the history
for #124
  • Loading branch information
snarfed committed Feb 26, 2019
1 parent b26dc69 commit 2cc72d2
Show file tree
Hide file tree
Showing 5 changed files with 76 additions and 27 deletions.
30 changes: 18 additions & 12 deletions api.py
Expand Up @@ -207,25 +207,31 @@ def write_response(self, response, actor=None, url=None, title=None,
reader = self.request.get('reader', 'true').lower()
if reader not in ('true', 'false'):
self.abort(400, 'reader param must be either true or false')
self.response.out.write(atom.activities_to_atom(
activities, actor,
host_url=url or self.request.host_url + '/',
request_url=self.request.url,
xml_base=util.base_url(url),
title=title,
rels={'hub': hub} if hub else None,
reader=(reader == 'true')))
try:
self.response.out.write(atom.activities_to_atom(
activities, actor,
host_url=url or self.request.host_url + '/',
request_url=self.request.url,
xml_base=util.base_url(url),
title=title,
rels={'hub': hub} if hub else None,
reader=(reader == 'true')))
except ValueError as e:
self.abort(400, str(e))
self.response.headers.add('Link', str('<%s>; rel="self"' % self.request.url))
if hub:
self.response.headers.add('Link', str('<%s>; rel="hub"' % hub))
elif format == 'rss':
self.response.headers['Content-Type'] = 'application/rss+xml'
if not title:
title = 'Feed for %s' % url
self.response.out.write(rss.from_activities(
activities, actor, title=title,
feed_url=self.request.url, hfeed=hfeed,
home_page_url=util.base_url(url)))
try:
self.response.out.write(rss.from_activities(
activities, actor, title=title,
feed_url=self.request.url, hfeed=hfeed,
home_page_url=util.base_url(url)))
except ValueError as e:
self.abort(400, str(e))
elif format in ('as1-xml', 'xml'):
self.response.headers['Content-Type'] = 'application/xml'
self.response.out.write(XML_TEMPLATE % util.to_xml(response))
Expand Down
35 changes: 21 additions & 14 deletions granary/rss.py
Expand Up @@ -55,8 +55,8 @@ def from_activities(activities, actor=None, title=None, feed_url=None,
fg.id(feed_url)
assert feed_url
fg.link(href=feed_url, rel='self')
fg.link(href=home_page_url, rel='alternate')
fg.title(title)
if home_page_url:
fg.link(href=home_page_url, rel='alternate')
# TODO: parse language from lang attribute:
# https://github.com/microformats/mf2py/issues/150
fg.language('en')
Expand All @@ -71,7 +71,9 @@ def from_activities(activities, actor=None, title=None, feed_url=None,
props = hfeed.get('properties') or {}
content = microformats2.get_text(util.get_first(props, 'content', ''))
summary = util.get_first(props, 'summary', '')
fg.description(content or summary or '-') # required
desc = content or summary or '-'
fg.description(desc) # required
fg.title(title or util.ellipsize(desc)) # required

latest = None
enclosures = False
Expand All @@ -92,8 +94,9 @@ def from_activities(activities, actor=None, title=None, feed_url=None,
if content:
item.content(content, type='CDATA')

item.category([{'term': t.displayName} for t in obj.get('tags', [])
if t.displayName and t.verb not in ('like', 'react', 'share')])
item.category(
[{'term': t['displayName']} for t in obj.get('tags', [])
if t.get('displayName') and t.get('verb') not in ('like', 'react', 'share')])

author = obj.get('author', {})
item.author({
Expand All @@ -103,14 +106,18 @@ def from_activities(activities, actor=None, title=None, feed_url=None,

published = obj.get('published') or obj.get('updated')
if published:
dt = mf2util.parse_datetime(published)
if not isinstance(dt, datetime):
dt = datetime.combine(dt, time.min)
if not dt.tzinfo:
dt = dt.replace(tzinfo=util.UTC)
item.published(dt)
if not latest or dt > latest:
latest = dt
try:
dt = mf2util.parse_datetime(published)
if not isinstance(dt, datetime):
dt = datetime.combine(dt, time.min)
if not dt.tzinfo:
dt = dt.replace(tzinfo=util.UTC)
item.published(dt)
if not latest or dt > latest:
latest = dt
except ValueError: # bad datetime string
pass


for att in obj.get('attachments', []):
stream = util.get_first(att, 'stream') or att
Expand Down Expand Up @@ -140,4 +147,4 @@ def from_activities(activities, actor=None, title=None, feed_url=None,
if latest:
fg.lastBuildDate(latest)

return fg.rss_str(pretty=True).decode().replace(' length="REMOVEME"', '')
return fg.rss_str(pretty=True).decode('utf-8').replace(' length="REMOVEME"', '')
29 changes: 29 additions & 0 deletions granary/tests/test_rss.py
@@ -0,0 +1,29 @@
# coding=utf-8
"""Unit tests for rss.py."""
from __future__ import absolute_import, unicode_literals

from granary import appengine_config
from oauth_dropins.webutil import testutil

from granary import rss


class RssTest(testutil.TestCase):

def test_from_activities_bad_published_datetime(self):
self.assert_multiline_in("""
<item>
<title>my post</title>
<link>http://perma/link</link>
<description>something</description>
<guid isPermaLink="true">http://perma/link</guid>
</item>
""",
rss.from_activities([{
'url': 'http://perma/link',
'objectType': 'article',
'displayName': 'my post',
'content': 'something',
'published': '2019',
}], feed_url='http://this'),
ignore_blanks=True)
8 changes: 7 additions & 1 deletion granary/tests/testdata/feed_with_audio_video.as.json
Expand Up @@ -10,11 +10,17 @@
"duration": 328
},
"objectType": "audio"
}],
"tags": [{
"displayName": "a tag"
}, {
"displayName": "not a tag",
"verb": "like"
}]
},
{
"url": "http://vidjo/post",
"objectType": "article",
"objectType": null,
"displayName": "i'm ready to perform",
"summary": "other thing",
"updated": "2012-12-04",
Expand Down
1 change: 1 addition & 0 deletions granary/tests/testdata/feed_with_audio_video.rss.xml
Expand Up @@ -33,6 +33,7 @@
<link>http://podcast/post</link>
<description>&lt;p&gt;some HTML&lt;/p&gt;</description>
<guid isPermaLink="true">http://podcast/post</guid>
<category>a tag</category>
<enclosure url="http://a/podcast.mp3" type="audio/mpeg"/>
<pubDate>Wed, 05 Dec 2012 00:58:26 +0700</pubDate>
<itunes:duration>328</itunes:duration>
Expand Down

0 comments on commit 2cc72d2

Please sign in to comment.