def rss_entry(self): """Create an RSS item using lxml's etree and return it. This is primarily used by :class:`podgen.Podcast` when generating the podcast's RSS feed. :returns: etree.Element('item') """ ITUNES_NS = 'http://www.itunes.com/dtds/podcast-1.0.dtd' DUBLIN_NS = 'http://purl.org/dc/elements/1.1/' entry = etree.Element('item') if not (self.title or self.summary): raise ValueError('Required fields not set, make sure either ' 'title or summary is set!') if self.title: title = etree.SubElement(entry, 'title') title.text = self.title if self.link: link = etree.SubElement(entry, 'link') link.text = self.link if self.summary or self.long_summary: if self.summary and self.long_summary: # Both are present, so use both content and description description = etree.SubElement(entry, 'description') description.text = etree.CDATA(self.summary) content = etree.SubElement(entry, '{%s}encoded' % 'http://purl.org/rss/1.0/modules/content/') content.text = etree.CDATA(self.long_summary) else: # Only one is present, use description because of support description = etree.SubElement(entry, 'description') description.text = \ etree.CDATA(self.summary or self.long_summary) if self.__authors: authors_with_name = [a.name for a in self.__authors if a.name] if authors_with_name: # We have something to display as itunes:author, combine all # names itunes_author = \ etree.SubElement(entry, '{%s}author' % ITUNES_NS) itunes_author.text = listToHumanreadableStr(authors_with_name) if len(self.__authors) > 1 or not self.__authors[0].email: # Use dc:creator, since it supports multiple authors (and # author without email) for a in self.__authors or []: author = etree.SubElement(entry, '{%s}creator' % DUBLIN_NS) if a.name and a.email: author.text = "%s <%s>" % (a.name, a.email) elif a.name: author.text = a.name else: author.text = a.email else: # Only one author and with email, so use rss author author = etree.SubElement(entry, 'author') author.text = str(self.__authors[0]) if self.id: rss_guid = self.id elif self.__media and self.id is None: rss_guid = self.__media.url else: # self.__rss_guid was set to boolean False, or no enclosure rss_guid = None if rss_guid: guid = etree.SubElement(entry, 'guid') guid.text = rss_guid guid.attrib['isPermaLink'] = 'false' if self.__media: enclosure = etree.SubElement(entry, 'enclosure') enclosure.attrib['url'] = self.__media.url enclosure.attrib['length'] = str(self.__media.size) enclosure.attrib['type'] = self.__media.type if self.__media.duration: duration = etree.SubElement(entry, '{%s}duration' % ITUNES_NS) duration.text = self.__media.duration_str if self.__publication_date: pubDate = etree.SubElement(entry, 'pubDate') pubDate.text = formatRFC2822(self.__publication_date) if self.__withhold_from_itunes: # It is True, so include element - otherwise, don't include it block = etree.SubElement(entry, '{%s}block' % ITUNES_NS) block.text = 'Yes' if self.__image: image = etree.SubElement(entry, '{%s}image' % ITUNES_NS) image.attrib['href'] = self.__image if self.__explicit is not None: explicit = etree.SubElement(entry, '{%s}explicit' % ITUNES_NS) explicit.text = "Yes" if self.__explicit else "No" if self.is_closed_captioned: is_closed_captioned = etree.SubElement(entry, '{%s}isClosedCaptioned' % ITUNES_NS) is_closed_captioned.text = 'Yes' if self.__position is not None and self.__position >= 0: order = etree.SubElement(entry, '{%s}order' % ITUNES_NS) order.text = str(self.__position) if self.subtitle: subtitle = etree.SubElement(entry, '{%s}subtitle' % ITUNES_NS) subtitle.text = self.subtitle return entry
def _create_rss(self): """Create an RSS feed XML structure containing all previously set fields. :returns: The root element (ie. the rss element) of the feed. :rtype: lxml.etree.Element """ ITUNES_NS = self._nsmap['itunes'] feed = etree.Element('rss', version='2.0', nsmap=self._nsmap) channel = etree.SubElement(feed, 'channel') if not (self.name and self.website and self.description and self.explicit is not None): missing = ', '.join( ([] if self.name else ['name']) + ([] if self.website else ['website']) + ([] if self.description else ['description']) + ([] if self.explicit is not None else ['explicit'])) raise ValueError('Required fields not set (%s)' % missing) title = etree.SubElement(channel, 'title') title.text = self.name link = etree.SubElement(channel, 'link') link.text = self.website desc = etree.SubElement(channel, 'description') desc.text = self.description explicit = etree.SubElement(channel, '{%s}explicit' % ITUNES_NS) explicit.text = "yes" if self.explicit else "no" if self.__cloud: cloud = etree.SubElement(channel, 'cloud') cloud.attrib['domain'] = self.__cloud.get('domain') cloud.attrib['port'] = str(self.__cloud.get('port')) cloud.attrib['path'] = self.__cloud.get('path') cloud.attrib['registerProcedure'] = self.__cloud.get( 'registerProcedure') cloud.attrib['protocol'] = self.__cloud.get('protocol') if self.copyright: copyright = etree.SubElement(channel, 'copyright') copyright.text = self.copyright if self.__docs: docs = etree.SubElement(channel, 'docs') docs.text = self.__docs if self.generator: generator = etree.SubElement(channel, 'generator') generator.text = self.generator if self.language: language = etree.SubElement(channel, 'language') language.text = self.language if self.last_updated is None: lastBuildDateDate = datetime.now(dateutil.tz.tzutc()) else: lastBuildDateDate = self.last_updated if lastBuildDateDate: lastBuildDate = etree.SubElement(channel, 'lastBuildDate') lastBuildDate.text = formatRFC2822(lastBuildDateDate) if self.authors: authors_with_name = [a.name for a in self.authors if a.name] if authors_with_name: # We have something to display as itunes:author, combine all # names itunes_author = \ etree.SubElement(channel, '{%s}author' % ITUNES_NS) itunes_author.text = listToHumanreadableStr(authors_with_name) if len(self.authors) > 1 or not self.authors[0].email: # Use dc:creator, since it supports multiple authors (and # author without email) for a in self.authors or []: author = etree.SubElement( channel, '{%s}creator' % self._nsmap['dc']) if a.name and a.email: author.text = "%s <%s>" % (a.name, a.email) elif a.name: author.text = a.name else: author.text = a.email else: # Only one author and with email, so use rss managingEditor author = etree.SubElement(channel, 'managingEditor') author.text = str(self.authors[0]) if self.publication_date is None: episode_dates = [ e.publication_date for e in self.episodes if e.publication_date is not None ] if episode_dates: actual_pubDate = max(episode_dates) else: actual_pubDate = None else: actual_pubDate = self.publication_date if actual_pubDate: pubDate = etree.SubElement(channel, 'pubDate') pubDate.text = formatRFC2822(actual_pubDate) if self.skip_hours: # Ensure any modifications to the set are accounted for self.skip_hours = self.skip_hours skipHours = etree.SubElement(channel, 'skipHours') for h in self.skip_hours: hour = etree.SubElement(skipHours, 'hour') hour.text = str(h) if self.skip_days: # Ensure any modifications to the set are accounted for self.skip_days = self.skip_days skipDays = etree.SubElement(channel, 'skipDays') for d in self.skip_days: day = etree.SubElement(skipDays, 'day') day.text = d if self.web_master: if not self.web_master.email: raise RuntimeError("webMaster must have an email. Did you " "set email to None after assigning that " "Person to webMaster?") webMaster = etree.SubElement(channel, 'webMaster') webMaster.text = str(self.web_master) if self.withhold_from_itunes: block = etree.SubElement(channel, '{%s}block' % ITUNES_NS) block.text = 'Yes' if self.category: category = etree.SubElement(channel, '{%s}category' % ITUNES_NS) category.attrib['text'] = self.category.category if self.category.subcategory: subcategory = etree.SubElement(category, '{%s}category' % ITUNES_NS) subcategory.attrib['text'] = self.category.subcategory if self.image: image = etree.SubElement(channel, '{%s}image' % ITUNES_NS) image.attrib['href'] = self.image if self.complete: complete = etree.SubElement(channel, '{%s}complete' % ITUNES_NS) complete.text = "Yes" if self.new_feed_url: new_feed_url = etree.SubElement(channel, '{%s}new-feed-url' % ITUNES_NS) new_feed_url.text = self.new_feed_url if self.owner: owner = etree.SubElement(channel, '{%s}owner' % ITUNES_NS) owner_name = etree.SubElement(owner, '{%s}name' % ITUNES_NS) owner_name.text = self.owner.name owner_email = etree.SubElement(owner, '{%s}email' % ITUNES_NS) owner_email.text = self.owner.email if self.subtitle: subtitle = etree.SubElement(channel, '{%s}subtitle' % ITUNES_NS) subtitle.text = self.subtitle if self.feed_url: link_to_self = etree.SubElement(channel, '{%s}link' % self._nsmap['atom']) link_to_self.attrib['href'] = self.feed_url link_to_self.attrib['rel'] = 'self' link_to_self.attrib['type'] = 'application/rss+xml' if self.pubsubhubbub: link_to_hub = etree.SubElement(channel, '{%s}link' % self._nsmap['atom']) link_to_hub.attrib['href'] = self.pubsubhubbub link_to_hub.attrib['rel'] = 'hub' for entry in self.episodes: item = entry.rss_entry() channel.append(item) return feed
def _create_rss(self): """Create an RSS feed XML structure containing all previously set fields. :returns: The root element (ie. the rss element) of the feed. :rtype: lxml.etree.Element """ ITUNES_NS = self._nsmap['itunes'] feed = etree.Element('rss', version='2.0', nsmap=self._nsmap) channel = etree.SubElement(feed, 'channel') if not (self.name and self.website and self.description and self.explicit is not None): missing = ', '.join(([] if self.name else ['title']) + ([] if self.website else ['link']) + ([] if self.description else ['description']) + ([] if self.explicit else ['itunes_explicit'])) raise ValueError('Required fields not set (%s)' % missing) title = etree.SubElement(channel, 'title') title.text = self.name link = etree.SubElement(channel, 'link') link.text = self.website desc = etree.SubElement(channel, 'description') desc.text = self.description explicit = etree.SubElement(channel, '{%s}explicit' % ITUNES_NS) explicit.text = "yes" if self.explicit else "no" if self.__cloud: cloud = etree.SubElement(channel, 'cloud') cloud.attrib['domain'] = self.__cloud.get('domain') cloud.attrib['port'] = str(self.__cloud.get('port')) cloud.attrib['path'] = self.__cloud.get('path') cloud.attrib['registerProcedure'] = self.__cloud.get( 'registerProcedure') cloud.attrib['protocol'] = self.__cloud.get('protocol') if self.copyright: copyright = etree.SubElement(channel, 'copyright') copyright.text = self.copyright if self.__docs: docs = etree.SubElement(channel, 'docs') docs.text = self.__docs if self.generator: generator = etree.SubElement(channel, 'generator') generator.text = self.generator if self.language: language = etree.SubElement(channel, 'language') language.text = self.language if self.last_updated is None: lastBuildDateDate = datetime.now(dateutil.tz.tzutc()) else: lastBuildDateDate = self.last_updated if lastBuildDateDate: lastBuildDate = etree.SubElement(channel, 'lastBuildDate') lastBuildDate.text = formatRFC2822(lastBuildDateDate) if self.authors: authors_with_name = [a.name for a in self.authors if a.name] if authors_with_name: # We have something to display as itunes:author, combine all # names itunes_author = \ etree.SubElement(channel, '{%s}author' % ITUNES_NS) itunes_author.text = listToHumanreadableStr(authors_with_name) if len(self.authors) > 1 or not self.authors[0].email: # Use dc:creator, since it supports multiple authors (and # author without email) for a in self.authors or []: author = etree.SubElement(channel, '{%s}creator' % self._nsmap['dc']) if a.name and a.email: author.text = "%s <%s>" % (a.name, a.email) elif a.name: author.text = a.name else: author.text = a.email else: # Only one author and with email, so use rss managingEditor author = etree.SubElement(channel, 'managingEditor') author.text = str(self.authors[0]) if self.publication_date is None: episode_dates = [e.publication_date for e in self.episodes if e.publication_date is not None] if episode_dates: actual_pubDate = max(episode_dates) else: actual_pubDate = None else: actual_pubDate = self.publication_date if actual_pubDate: pubDate = etree.SubElement(channel, 'pubDate') pubDate.text = formatRFC2822(actual_pubDate) if self.skip_hours: # Ensure any modifications to the set are accounted for self.skip_hours = self.skip_hours skipHours = etree.SubElement(channel, 'skipHours') for h in self.skip_hours: hour = etree.SubElement(skipHours, 'hour') hour.text = str(h) if self.skip_days: # Ensure any modifications to the set are accounted for self.skip_days = self.skip_days skipDays = etree.SubElement(channel, 'skipDays') for d in self.skip_days: day = etree.SubElement(skipDays, 'day') day.text = d if self.web_master: if not self.web_master.email: raise RuntimeError("webMaster must have an email. Did you " "set email to None after assigning that " "Person to webMaster?") webMaster = etree.SubElement(channel, 'webMaster') webMaster.text = str(self.web_master) if self.withhold_from_itunes: block = etree.SubElement(channel, '{%s}block' % ITUNES_NS) block.text = 'Yes' if self.category: category = etree.SubElement(channel, '{%s}category' % ITUNES_NS) category.attrib['text'] = self.category.category if self.category.subcategory: subcategory = etree.SubElement(category, '{%s}category' % ITUNES_NS) subcategory.attrib['text'] = self.category.subcategory if self.image: image = etree.SubElement(channel, '{%s}image' % ITUNES_NS) image.attrib['href'] = self.image if self.complete: complete = etree.SubElement(channel, '{%s}complete' % ITUNES_NS) complete.text = "Yes" if self.new_feed_url: new_feed_url = etree.SubElement(channel, '{%s}new-feed-url' % ITUNES_NS) new_feed_url.text = self.new_feed_url if self.owner: owner = etree.SubElement(channel, '{%s}owner' % ITUNES_NS) owner_name = etree.SubElement(owner, '{%s}name' % ITUNES_NS) owner_name.text = self.owner.name owner_email = etree.SubElement(owner, '{%s}email' % ITUNES_NS) owner_email.text = self.owner.email if self.subtitle: subtitle = etree.SubElement(channel, '{%s}subtitle' % ITUNES_NS) subtitle.text = self.subtitle if self.feed_url: link_to_self = etree.SubElement(channel, '{%s}link' % self._nsmap['atom']) link_to_self.attrib['href'] = self.feed_url link_to_self.attrib['rel'] = 'self' link_to_self.attrib['type'] = 'application/rss+xml' if self.pubsubhubbub: link_to_hub = etree.SubElement(channel, '{%s}link' % self._nsmap['atom']) link_to_hub.attrib['href'] = self.pubsubhubbub link_to_hub.attrib['rel'] = 'hub' for entry in self.episodes: item = entry.rss_entry() channel.append(item) return feed