1 """Feeds for Zinnia"""
2 from sgmllib import SGMLParser
3
4 from django.contrib.auth.models import User
5 from django.contrib.sites.models import Site
6 from django.core.urlresolvers import reverse
7 from django.core.urlresolvers import NoReverseMatch
8 from django.utils.feedgenerator import Atom1Feed
9 from django.utils.translation import ugettext as _
10 from django.contrib.syndication.views import Feed
11 from django.shortcuts import get_object_or_404
12
13 from tagging.models import Tag
14 from tagging.models import TaggedItem
15
16 from zinnia.models import Entry
17 from zinnia.settings import COPYRIGHT
18 from zinnia.settings import PROTOCOL
19 from zinnia.settings import FEEDS_MAX_ITEMS
20 from zinnia.managers import entries_published
21 from zinnia.views.categories import get_category_or_404
22
23
25 """Parser for getting IMG markups"""
26
28 SGMLParser.__init__(self)
29 self.img_locations = []
30
32 """Save each image's location"""
33 attr = dict(attr)
34 if attr.get('src', ''):
35 self.img_locations.append(attr['src'])
36
37
38 -class EntryFeed(Feed):
39 """Base Entry Feed"""
40 title_template = 'feeds/entry_title.html'
41 description_template = 'feeds/entry_description.html'
42 feed_copyright = COPYRIGHT
43
45 self.site = Site.objects.get_current()
46
47 - def item_pubdate(self, item):
48 """Publication date of an entry"""
49 return item.creation_date
50
51 - def item_categories(self, item):
52 """Entry's categories"""
53 return [category.title for category in item.categories.all()]
54
55 - def item_author_name(self, item):
56 """Returns the first author of an entry"""
57 return item.authors.all()[0].username
58
59 - def item_author_email(self, item):
60 """Returns the first author's email"""
61 return item.authors.all()[0].email
62
63 - def item_author_link(self, item):
64 """Returns the author's URL"""
65 url = '%s://%s' % (PROTOCOL, self.site.domain)
66 try:
67 author_url = reverse('zinnia_author_detail',
68 args=[item.authors.all()[0].username])
69 return url + author_url
70 except NoReverseMatch:
71 return url
72
73 - def item_enclosure_url(self, item):
74 """Returns an image for enclosure"""
75 if item.image:
76 return item.image.url
77 parser = ImgParser()
78 try:
79 parser.feed(item.content)
80 except UnicodeEncodeError:
81 return
82 if len(parser.img_locations):
83 if self.site.domain in parser.img_locations[0]:
84 return parser.img_locations[0]
85 else:
86 return '%s://%s%s' % (PROTOCOL,
87 self.site.domain,
88 parser.img_locations[0])
89 return None
90
92 """Hardcoded enclosure length"""
93 return '100000'
94
96 """Hardcoded enclosure mimetype"""
97 return 'image/jpeg'
98
99
101 """Feed for the latest entries"""
102 title = _('Latest entries')
103
105 """URL of latest entries"""
106 return reverse('zinnia_entry_archive_index')
107
111
113 """Description of the feed"""
114 return _('The latest entries for the site %s') % self.site.domain
115
116
118 """Feed filtered by a category"""
119
123
127
128 - def link(self, obj):
131
133 """Title of the feed"""
134 return _('Entries for the category %s') % obj.title
135
137 """Description of the feed"""
138 return _('The latest entries for the category %s') % obj.title
139
140
142 """Feed filtered by an author"""
143
145 """Retrieve the author by his username"""
146 return get_object_or_404(User, username=username)
147
151
152 - def link(self, obj):
153 """URL of the author"""
154 return reverse('zinnia_author_detail', args=[obj.username])
155
157 """Title of the feed"""
158 return _('Entries for author %s') % obj.username
159
161 """Description of the feed"""
162 return _('The latest entries by %s') % obj.username
163
164
166 """Feed filtered by a tag"""
167
169 """Retrieve the tag by his name"""
170 return get_object_or_404(Tag, name=slug)
171
176
177 - def link(self, obj):
178 """URL of the tag"""
179 return reverse('zinnia_tag_detail', args=[obj.name])
180
182 """Title of the feed"""
183 return _('Entries for the tag %s') % obj.name
184
186 """Description of the feed"""
187 return _('The latest entries for the tag %s') % obj.name
188
189
191 """Feed filtered by a search pattern"""
192
194 """The slug is the pattern to search"""
195 return slug
196
200
201 - def link(self, obj):
202 """URL of the search request"""
203 return '%s?pattern=%s' % (reverse('zinnia_entry_search'), obj)
204
206 """Title of the feed"""
207 return _('Results of the search for %s') % obj
208
210 """Description of the feed"""
211 return _('The entries containing the pattern %s') % obj
212
213
214 -class EntryDiscussions(Feed):
215 """Feed for discussions in an entry"""
216 title_template = 'feeds/discussion_title.html'
217 description_template = 'feeds/discussion_description.html'
218 feed_copyright = COPYRIGHT
219
220 - def get_object(self, request, slug):
221 """Retrieve the discussions by entry's slug"""
222 return get_object_or_404(Entry, slug=slug)
223
224 - def items(self, obj):
225 """Items are the discussions on the entry"""
226 return obj.discussions[:FEEDS_MAX_ITEMS]
227
228 - def item_pubdate(self, item):
229 """Publication date of a discussion"""
230 return item.submit_date
231
232 - def item_link(self, item):
233 """URL of the discussion"""
234 return item.get_absolute_url()
235
236 - def link(self, obj):
237 """URL of the entry"""
238 return obj.get_absolute_url()
239
240 - def item_author_name(self, item):
241 """Author of the discussion"""
242 return item.userinfo['name']
243
244 - def item_author_email(self, item):
245 """Author's email of the discussion"""
246 return item.userinfo['email']
247
248 - def item_author_link(self, item):
249 """Author's URL of the discussion"""
250 return item.userinfo['url']
251
252 - def title(self, obj):
253 """Title of the feed"""
254 return _('Discussions on %s') % obj.title
255
256 - def description(self, obj):
257 """Description of the feed"""
258 return _('The latest discussions for the entry %s') % obj.title
259
260
262 """Feed for comments in an entry"""
263 title_template = 'feeds/comment_title.html'
264 description_template = 'feeds/comment_description.html'
265
269
271 """URL of the comment"""
272 return item.get_absolute_url('#comment_%(id)s')
273
275 """Title of the feed"""
276 return _('Comments on %s') % obj.title
277
279 """Description of the feed"""
280 return _('The latest comments for the entry %s') % obj.title
281
282
283 -class EntryPingbacks(EntryDiscussions):
284 """Feed for pingbacks in an entry"""
285 title_template = 'feeds/pingback_title.html'
286 description_template = 'feeds/pingback_description.html'
287
288 - def items(self, obj):
289 """Items are the pingbacks on the entry"""
290 return obj.pingbacks[:FEEDS_MAX_ITEMS]
291
292 - def item_link(self, item):
293 """URL of the pingback"""
294 return item.get_absolute_url('#pingback_%(id)s')
295
296 - def title(self, obj):
297 """Title of the feed"""
298 return _('Pingbacks on %s') % obj.title
299
300 - def description(self, obj):
301 """Description of the feed"""
302 return _('The latest pingbacks for the entry %s') % obj.title
303
304
305 -class EntryTrackbacks(EntryDiscussions):
306 """Feed for trackbacks in an entry"""
307 title_template = 'feeds/trackback_title.html'
308 description_template = 'feeds/trackback_description.html'
309
310 - def items(self, obj):
311 """Items are the trackbacks on the entry"""
312 return obj.trackbacks[:FEEDS_MAX_ITEMS]
313
314 - def item_link(self, item):
315 """URL of the trackback"""
316 return item.get_absolute_url('#trackback_%(id)s')
317
318 - def title(self, obj):
319 """Title of the feed"""
320 return _('Trackbacks on %s') % obj.title
321
322 - def description(self, obj):
323 """Description of the feed"""
324 return _('The latest trackbacks for the entry %s') % obj.title
325
326
327
332
333
338
339
344
345
350
351
356
357
358 -class AtomEntryDiscussions(EntryDiscussions):
359 """Atom feed for discussions in an entry"""
360 feed_type = Atom1Feed
361 subtitle = EntryDiscussions.description
362
363
368
369
370 -class AtomEntryPingbacks(EntryPingbacks):
371 """Atom feed for pingbacks in an entry"""
372 feed_type = Atom1Feed
373 subtitle = EntryPingbacks.description
374
375
376 -class AtomEntryTrackbacks(EntryTrackbacks):
377 """Atom feed for trackbacks in an entry"""
378 feed_type = Atom1Feed
379 subtitle = EntryTrackbacks.description
380