Source code for ls.joyous.formats.rss

# ------------------------------------------------------------------------------
# RSS Feed Export Handler
# ------------------------------------------------------------------------------
import datetime as dt
from django.http import HttpResponse
from django.conf import settings
from django.template import loader
from django.templatetags.static import static
from ..models import (CalendarPage, SimpleEventPage, MultidayEventPage,
        RecurringEventPage, ExtraInfoPage, CancellationBase, PostponementPage)
from feedgen.feed import FeedGenerator
from feedgen.entry import FeedEntry
from .errors import CalendarTypeError

# ------------------------------------------------------------------------------
[docs]class RssHandler: """Serve a RSS Feed""" def serve(self, page, request, *args, **kwargs): try: feed = CalendarFeed.fromPage(page, request) except CalendarTypeError: return None response = HttpResponse(feed.rss_str(), content_type='application/xml; charset=utf-8') return response
# ------------------------------------------------------------------------------ def fullUrl(url, page, request): """Convert a relative url to a full url""" siteId, root, path = page.get_url_parts(request) if not url.startswith(root): url = root + url return url # ------------------------------------------------------------------------------ class CalendarFeed(FeedGenerator): """Produce a feed of upcoming events""" imagePath = static("joyous/img/logo.png") @classmethod def fromPage(cls, page, request): if isinstance(page, CalendarPage): return cls._fromCalendarPage(page, request) else: raise CalendarTypeError("Unsupported input page") @classmethod def _fromCalendarPage(cls, page, request): feed = cls() feed.title(page.title) feed.link(href=page.get_full_url(request)) feed.author(name=page.owner.get_full_name()) feed.description(page.intro or page.title) feed.generator("ls.joyous") imagePath = getattr(settings, "JOYOUS_RSS_FEED_IMAGE", cls.imagePath) feed.image(url=fullUrl(imagePath, page, request)) for thisEvent in page._getUpcomingEvents(request): entry = cls._makeFromEvent(thisEvent, request) feed.entry(entry) return feed @classmethod def _makeFromEvent(cls, thisEvent, request): page = thisEvent.page if isinstance(page, (SimpleEventPage, MultidayEventPage, RecurringEventPage, PostponementPage)): return EventEntry.fromEvent(thisEvent, request) elif isinstance(page, ExtraInfoPage): return ExtraInfoEntry.fromEvent(thisEvent, request) elif isinstance(page, CancellationBase): return CancellationEntry.fromEvent(thisEvent, request) # ------------------------------------------------------------------------------ class EventEntry(FeedEntry): template = "joyous/formats/rss_entry.xml" @classmethod def fromEvent(cls, thisEvent, request): page = thisEvent.page entry = cls() entry.title(thisEvent.title) url = fullUrl(thisEvent.url, page, request) entry.link(href=url) entry.guid(url, permalink=True) entry.setDescription(thisEvent, request) entry.setCategory(page) entry.setImage(page, request) entry.author(name=page.owner.get_full_name()) entry.published(page.first_published_at) entry.updated(page.last_published_at) return entry def setDescription(self, thisEvent, request): page = thisEvent.page tmpl = loader.get_template(self.template) ctxt = {'event': page, 'title': thisEvent.title, 'details': page.details, 'request': request} descr = tmpl.render(ctxt, request) self.description(descr) # NOTE: feedgen will escape the HTML and that is a GOOD THING def setCategory(self, page): category = page.category if category: self.category(term=category.name) def setImage(self, page, request): image = page.image if image: ren = image.get_rendition("width-350|format-png") self.enclosure(url=fullUrl(ren.url, page, request), length=str(len(ren.file)), type="image/png") # ------------------------------------------------------------------------------ class ExtraInfoEntry(EventEntry): template = "joyous/formats/rss_extra_info_entry.xml" def setDescription(self, thisEvent, request): page = thisEvent.page tmpl = loader.get_template(self.template) ctxt = {'event': page, 'title': thisEvent.title, 'extra_information': page.extra_information, 'details': page.overrides.details, 'request': request} descr = tmpl.render(ctxt, request) self.description(descr) # ------------------------------------------------------------------------------ class CancellationEntry(EventEntry): template = "joyous/formats/rss_cancellation_entry.xml" def setDescription(self, thisEvent, request): page = thisEvent.page tmpl = loader.get_template(self.template) ctxt = {'event': page, 'title': thisEvent.title, 'cancellation_details': page.cancellation_details, 'request': request} descr = tmpl.render(ctxt, request) self.description(descr) # ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------