Skip to content

Commit 7161a72

Browse files
committed
Merged in [10345] from rjsparks@nostrum.com:
Added an RSS feed for RFCs for use with the digital preservation project. - Legacy-Id: 10358 Note: SVN reference [10345] has been migrated to Git commit 5daee49
2 parents cb0f0aa + 5daee49 commit 7161a72

3 files changed

Lines changed: 87 additions & 3 deletions

File tree

ietf/doc/feeds.py

Lines changed: 80 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
# Copyright The IETF Trust 2007, All Rights Reserved
22

3+
import datetime
4+
35
from django.contrib.syndication.views import Feed, FeedDoesNotExist
4-
from django.utils.feedgenerator import Atom1Feed
6+
from django.utils.feedgenerator import Atom1Feed, Rss201rev2Feed
57
from django.core.urlresolvers import reverse as urlreverse
68
from django.template.defaultfilters import truncatewords, truncatewords_html, date as datefilter, linebreaks
79
from django.utils.html import strip_tags
810

9-
from ietf.doc.models import Document, State, LastCallDocEvent
11+
from ietf.doc.models import Document, State, LastCallDocEvent, DocEvent
1012
from ietf.doc.utils import augment_events_with_revision
1113
from ietf.doc.templatetags.ietf_filters import format_textarea
1214

@@ -75,3 +77,79 @@ def item_description(self, item):
7577
def item_pubdate(self, item):
7678
return item.lc_event.time
7779

80+
class Rss201WithNamespacesFeed(Rss201rev2Feed):
81+
def root_attributes(self):
82+
attrs = super(Rss201WithNamespacesFeed, self).root_attributes()
83+
attrs['xmlns:dcterms'] = 'http://purl.org/dc/terms/'
84+
attrs['xmlns:media'] = 'http://search.yahoo.com/mrss/'
85+
attrs['xmlns:xsi'] = 'http://www.w3.org/2001/XMLSchema-instance'
86+
return attrs
87+
88+
def add_item_elements(self, handler, item):
89+
super(Rss201WithNamespacesFeed, self).add_item_elements(handler, item)
90+
91+
for element_name in ['abstract','accessRights', 'format', ]:
92+
dc_item_name = 'dcterms_%s' % element_name
93+
dc_element_name = 'dcterms:%s' % element_name
94+
if dc_item_name in item and item[dc_item_name] is not None:
95+
handler.addQuickElement(dc_element_name,item[dc_item_name])
96+
97+
if 'doi' in item and item['doi'] is not None:
98+
handler.addQuickElement('dcterms:identifier',item['doi'],{'xsi:type':'dcterms:doi'})
99+
100+
if 'media_content' in item and item['media_content'] is not None:
101+
handler.startElement('media:content',{'url':item['media_content']['url'],'type':'text/plain'})
102+
handler.addQuickElement('dcterms:isFormatOf',item['media_content']['link_url'])
103+
handler.endElement('media:content')
104+
105+
class RfcFeed(Feed):
106+
feed_type = Rss201WithNamespacesFeed
107+
title = "RFCs"
108+
author_name = "RFC Editor"
109+
link = "https://www.rfc-editor.org/rfc-index2.html"
110+
111+
def items(self):
112+
cutoff = datetime.datetime.now() - datetime.timedelta(days=8)
113+
rfc_events = DocEvent.objects.filter(type='published_rfc',time__gte=cutoff).order_by('-time')
114+
results = [(e.doc, e.time) for e in rfc_events]
115+
for doc,time in results:
116+
doc.publication_time = time
117+
return [doc for doc,time in results]
118+
119+
def item_title(self, item):
120+
return item.canonical_name()
121+
122+
def item_description(self, item):
123+
return item.title
124+
125+
def item_link(self, item):
126+
return "https://rfc-editor.org/info/%s"%item.canonical_name()
127+
128+
def item_pubdate(self, item):
129+
return item.publication_time
130+
131+
def item_extra_kwargs(self, item):
132+
extra = super(RfcFeed, self).item_extra_kwargs(item)
133+
extra.update({'dcterms_abstract': item.abstract})
134+
extra.update({'dcterms_accessRights': 'gratis'})
135+
extra.update({'dcterms_format': 'text/html'})
136+
extra.update({'media_content': {'url': 'https://rfc-editor.org/rfc/%s.txt' % item.canonical_name(),
137+
'link_url': self.item_link(item)
138+
}
139+
})
140+
extra.update({'doi':'http://dx.doi.org/10.17487/%s' % item.canonical_name().upper()})
141+
142+
#TODO
143+
# R104 Publisher (Mandatory - but we need a string from them first)
144+
145+
#TODO MAYBE (Optional stuff)
146+
# R108 License
147+
# R115 Creator/Contributor (which would we use?)
148+
# F305 Checksum (do they use it?) (or should we put the our digital signature in here somewhere?)
149+
# F308 Holder of rights (copyright)
150+
151+
# Stuff we can't do yet given what's in the datatracker
152+
# R118 Keyword
153+
154+
return extra
155+

ietf/doc/tests.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -756,6 +756,11 @@ def test_last_call_feed(self):
756756
self.assertEqual(r.status_code, 200)
757757
self.assertTrue(doc.name in r.content)
758758

759+
def test_rfc_feed(self):
760+
make_test_data()
761+
r = self.client.get("/feed/rfc/")
762+
self.assertTrue(r.status_code, 200)
763+
759764
def test_state_help(self):
760765
url = urlreverse('state_help', kwargs=dict(type="draft-iesg"))
761766
r = self.client.get(url)

ietf/feed_urls.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from django.conf.urls import patterns
22
from django.views.generic import RedirectView
33

4-
from ietf.doc.feeds import DocumentChangesFeed, InLastCallFeed
4+
from ietf.doc.feeds import DocumentChangesFeed, InLastCallFeed, RfcFeed
55
from ietf.group.feeds import GroupChangesFeed
66
from ietf.iesg.feeds import IESGAgendaFeed
77
from ietf.ipr.feeds import LatestIprDisclosuresFeed
@@ -18,4 +18,5 @@
1818
(r'^ipr/$', LatestIprDisclosuresFeed()),
1919
(r'^liaison/(?P<kind>recent|from|to|subject)/(?:(?P<search>[^/]+)/)?$', LiaisonStatementsFeed()),
2020
(r'^wg-proceedings/$', LatestMeetingMaterialFeed()),
21+
(r'^rfc/$', RfcFeed())
2122
)

0 commit comments

Comments
 (0)