diff --git a/www/conservancy/feeds.py b/www/conservancy/feeds.py index d71b02935d62bc7bc3039419597d516b1c7b8221..a566cff2fd960d2c9db8157569da67e99e1e6f66 100644 --- a/www/conservancy/feeds.py +++ b/www/conservancy/feeds.py @@ -1,9 +1,37 @@ from django.contrib.syndication.feeds import Feed +from django.utils.feedgenerator import Rss201rev2Feed from conservancy.apps.news.models import PressRelease +from conservancy.apps.blog.models import Entry as BlogEntry from django.shortcuts import render_to_response from django.conf import settings -import datetime +from datetime import datetime + +import itertools +import operator + +class ConservancyFeedBase(Feed): + def copyright_holder(self): return "Software Freedom Conservancy" + + def license_no_html(self): return "Licensed under the Creative Commons Attribution-ShareAlike 3.0 Unported License." + + def item_copyright(self, item): + year = 2008 + for attr in ('pub_date', 'date_created', 'date_last_modified'): + if hasattr(item, attr): + if hasattr(getattr(item, attr), 'year'): + year = getattr(getattr(item, attr), 'year') + break + return 'Copyright (C) %d, %s. %s' % (year, self.copyright_holder(), self.license_no_html()) + + def item_extra_kwargs(self, item): + year = 2008 + for attr in ('pub_date', 'date_created', 'date_last_modified'): + if hasattr(item, attr): + if hasattr(getattr(item, attr), 'year'): + year = getattr(getattr(item, attr), 'year') + break + return { 'year' : year } class PressReleaseFeed(Feed): title = "Software Freedom Conservancy News" @@ -11,17 +39,213 @@ class PressReleaseFeed(Feed): description = "" def items(self): - return PressRelease.objects.filter(pub_date__lte=datetime.datetime.now(), + return PressRelease.objects.filter(pub_date__lte=datetime.now(), sites__id__exact=settings.SITE_ID).order_by('-pub_date')[:10] def item_pubdate(self, item): return item.pub_date +class OmnibusFeedType(Rss201rev2Feed): + def root_attributes(self): + attrs = super(OmnibusFeedType, self).root_attributes() + attrs['xmlns:itunes'] = 'http://www.itunes.com/dtds/podcast-1.0.dtd' + attrs['xmlns:atom'] = 'http://www.w3.org/2005/Atom' + attrs['xmlns:media'] = 'http://search.yahoo.com/mrss/' + attrs['xmlns:dc'] = "http://purl.org/dc/elements/1.1/" + return attrs + + def add_root_elements(self, handler): + super(OmnibusFeedType, self).add_root_elements(handler) + + def add_item_elements(self, handler, item): + super(OmnibusFeedType, self).add_item_elements(handler, item) + # Block things that don't have an enclosure from iTunes in + # case someone uploads this feed there. + handler.addQuickElement("itunes:block", 'Yes') + +class OmnibusFeed(ConservancyFeedBase): + feed_type = OmnibusFeedType + link ="/omnibus/" + title = "The Software Freedom Conservancy" + description = "An aggregated feed of all RSS content available from the Software Freedom Conservancy, including both news items and blogs." + title_template = "feeds/omnibus_title.html" + description_template = "feeds/omnibus_description.html" + author_email = "info@sfconservancy.org" + author_link = "http://sfconservancy.org/" + author_name = "Software Freedom Conservancy" + + def item_enclosure_mime_type(self): return "audio/mpeg" + + def item_enclosure_url(self, item): + if hasattr(item, 'mp3_path'): + return "http://sfconservancy.org" + item.mp3_path + def item_enclosure_length(self, item): + if hasattr(item, 'mp3_path'): + return item.mp3_length + + def item_pubdate(self, item): + return item.pub_date + + def item_author_name(self, item): + if item.omnibus_type == "blog": + return item.author.formal_name + else: + return "Software Freedom Conservancy" + + def item_author_link(self, obj): + return "http://sfconservancy.org" + + def item_author_email(self, item): + if item.omnibus_type == "news": + return "info@sfconservancy.org" + elif hasattr(item, 'author'): + return "%s@sfconservancy.org" % item.author + else: + return "info@sfconservancy.org" + + def item_pubdate(self, item): + if item.omnibus_type == "event": + return item.date_created + else: + return item.pub_date + + def item_link(self, item): + return item.get_absolute_url() + +# http://groups.google.ca/group/django-users/browse_thread/thread/d22e8a8f378cf0e2 + + def items(self): + blogs = BlogEntry.objects.filter(pub_date__lte=datetime.now()).order_by('-pub_date')[:25] + for bb in blogs: + bb.omnibus_type = "blog" + bb.omnibus_feed_description_template = "feeds/blog_description.html" + bb.omnibus_feed_title_template = "feeds/blog_title.html" + + news = PressRelease.objects.filter(pub_date__lte=datetime.now(), + sites__id__exact=settings.SITE_ID).order_by('-pub_date')[:25] + for nn in news: + nn.omnibus_type = "news" + nn.omnibus_feed_description_template = "feeds/news_description.html" + nn.omnibus_feed_title_template = "feeds/news_title.html" + + a = [ ii for ii in itertools.chain(blogs, news)] + a.sort(key=operator.attrgetter('pub_date'), reverse=True) + return a + + + def item_extra_kwargs(self, item): + return super(OmnibusFeed, self).item_extra_kwargs(item) + +class BlogFeed(ConservancyFeedBase): + link = "/blog/" + + def title(self): + answer = "The Software Freedom Conservancy Blog" + + GET = self.request.GET + tags = [] + if 'author' in GET: + tags = GET.getlist('author') + if 'tag' in GET: + tags += GET.getlist('tag') + + if len(tags) == 1: + answer += " (" + tags[0] + ")" + elif len(tags) > 1: + firstTime = True + done = {} + for tag in tags: + if done.has_key(tag): continue + if firstTime: + answer += " (" + firstTime = False + else: + answer += ", " + answer += tag + done[tag] = tag + answer += ")" + else: + answer += "." + return answer + + def description(self): + answer = "Blogs at the Software Freedom Conservancy" + + GET = self.request.GET + tags = [] + if 'author' in GET: tags = GET.getlist('author') + if 'tag' in GET: tags += GET.getlist('tag') + + done = {} + if len(tags) == 1: + answer += " tagged with " + tags[0] + elif len(tags) > 1: + firstTime = True + for tag in tags: + if done.has_key(tag): continue + if firstTime: + answer += " tagged with " + firstTime = False + else: + answer += " or " + answer += tag + done[tag] = tag + else: + answer = "All blogs at the Software Freedom Conservancy" + answer += "." + + return answer + + def item_author_name(self, item): + return item.author.formal_name + + def item_author_email(self, item): + GET = self.request.GET + if not 'author' in GET: + return "%s@sfconservancy.org" % item.author + else: + answer = "" + authors = GET.getlist('author') + firstTime = True + for author in authors: + if not firstTime: + answer = "%s@sfconservancy.org" % author + firstTime = False + else: + answer += ",%s@sfconservancy.org" % author + + def item_pubdate(self, item): + return item.pub_date + def items(self): + GET = self.request.GET + + def OR_filter(field_name, subfield_name, objs): + from django.db.models import Q + return reduce(lambda x, y: x | y, + [Q(**{'%s__%s' % (field_name, subfield_name): x}) + for x in objs]) + + queryset = BlogEntry.objects.filter(pub_date__lte=datetime.now()) + + if 'author' in GET: + authors = GET.getlist('author') + queryset = queryset.filter(OR_filter('author', 'username', authors)) + + if 'tag' in GET: + tags = GET.getlist('tag') + queryset = queryset.filter(OR_filter('tags', 'slug', tags)) + + return queryset.order_by('-pub_date')[:10] + + feed_dict = { + 'blog': BlogFeed, 'news': PressReleaseFeed, + 'omnibus': OmnibusFeed, +# 'event-media': RecentEventMediaFeed, } - # make each feed know its canonical url + for k, v in feed_dict.items(): v.get_absolute_url = '/feeds/%s/' % k @@ -29,4 +253,5 @@ def view(request): """Listing of all available feeds """ - return render_to_response("feeds.html", {'feeds': feed_dict.values()}) + feeds = feed_dict.values() + return render_to_response("feeds.html", {'feeds': feeds}) diff --git a/www/conservancy/templates/base_blog.html b/www/conservancy/templates/base_blog.html index d5c1ff47d7d56f9e5a716abd8bd348d24284c9b5..69e2e7c1e0b608e329592d169645ce87385693bc 100644 --- a/www/conservancy/templates/base_blog.html +++ b/www/conservancy/templates/base_blog.html @@ -1,4 +1,4 @@ -{% extends "base_standard.html" %} +{% extends "base_conservancy.html" %} {% block category %}blog{% endblock %} @@ -6,9 +6,10 @@ {% endblock %} -{% block internal_navigate %} - -

Authors

+{% block outercontent %} +
+ +
{% block content %}{% endblock %} +
+
{% endblock %} diff --git a/www/conservancy/templates/base_conservancy.html b/www/conservancy/templates/base_conservancy.html index 5945f53c715b2537cc4d040be7dc452398f2c1f4..f5759af35f121e99011dff8aee24f36998af0840 100644 --- a/www/conservancy/templates/base_conservancy.html +++ b/www/conservancy/templates/base_conservancy.html @@ -31,7 +31,7 @@ {% block outercontent %}
{% block content %}{% endblock %}
{% endblock %}
-

Main Page | Contact | Privacy Policy | News Feed

+

Main Page | Contact | Privacy Policy | RSS Feed

Blog post by {{ obj.author.formal_name }}. Please email any comments on this entry to <{{ obj.author.username }}@softwarefreedom.org>.

+{{ obj.body|safe }} diff --git a/www/conservancy/templates/feeds/blog_title.html b/www/conservancy/templates/feeds/blog_title.html new file mode 100644 index 0000000000000000000000000000000000000000..41fedac79fb4d9f8b2449b000ab5dbaa594dc417 --- /dev/null +++ b/www/conservancy/templates/feeds/blog_title.html @@ -0,0 +1 @@ +{{ obj.headline|striptags|safe }} diff --git a/www/conservancy/templates/frontpage.html b/www/conservancy/templates/frontpage.html index f6234231ad5c1f4845172eb6f8c43fbe4c677b23..387e348969ea4c20c09ab36a384c1811c531ad94 100644 --- a/www/conservancy/templates/frontpage.html +++ b/www/conservancy/templates/frontpage.html @@ -2,7 +2,9 @@ {% load date_within %} {% block head %} + + {% endblock %} {% block content %} @@ -29,7 +31,13 @@ Conservancy's current member projects… Services that Conservancy provides to its member projects…

-

Support Conservancy!

+

Follow Conservancy RSS Feeds

+ +

There is a full site feed available, as + well as separate feeds for the news items and + blog posts.

+ +

Support Conservancy

As a 501(c)(3) non-profit organization, Conservancy relies on charitable donations for its operations. Please donate generously to help our work! diff --git a/www/conservancy/templates/news/pressrelease_detail.html b/www/conservancy/templates/news/pressrelease_detail.html index 4af71832a3a437a52fc612e8424155d44103c252..acc3fac45d05137d7dd9af6586e65bafa0bae091 100644 --- a/www/conservancy/templates/news/pressrelease_detail.html +++ b/www/conservancy/templates/news/pressrelease_detail.html @@ -4,6 +4,7 @@ {% block content %} +

{{ object.pub_date|date:"F j, Y" }}

{{ object.headline|safe }}

{% if object.subhead %} @@ -13,5 +14,5 @@ {{ object.summary|safe }} {{ object.body|safe }} - +
{% endblock %}