CSRF protection. #361
[zzz-spline-forum.git] / splinext / forum / frontpage_sources.py
1 from collections import namedtuple
2
3 from sqlalchemy.orm import contains_eager, joinedload
4 from pylons import url
5
6 from spline.model import meta
7
8 from splinext.forum import model as forum_model
9 from splinext.frontpage.sources import Source
10
11 def frontpage_hook(limit, max_age, forum_id):
12 """Hook to return recent news for the front page."""
13
14 FrontPageThread = namedtuple('FrontPageThread', ['source', 'time', 'post'])
15 class ForumSource(Source):
16 """Represents a forum whose threads are put on the front page.
17
18 ``link``, ``title``, and ``icon`` are all optional; the link and title
19 default to the forum's thread list and name, and the icon defaults to a
20 newspaper.
21
22 Extra properties:
23
24 ``forum_id``
25 id of the forum to check for new threads.
26 """
27
28 template = '/forum/front_page.mako'
29
30 def __init__(self, forum_id, **kwargs):
31 forum = meta.Session.query(forum_model.Forum).get(forum_id)
32
33 # Link is tricky. Needs url(), which doesn't exist when this class is
34 # loaded. Lazy-load it in poll() below, instead
35 kwargs.setdefault('link', None)
36 kwargs.setdefault('title', forum.name)
37 kwargs.setdefault('icon', 'newspapers')
38 super(ForumSource, self).__init__(**kwargs)
39
40 self.forum_id = forum_id
41
42 def _poll(self, limit, max_age):
43 if not self.link:
44 self.link = url(
45 controller='forum', action='threads', forum_id=self.forum_id)
46
47 thread_q = meta.Session.query(forum_model.Thread) \
48 .filter_by(forum_id=self.forum_id) \
49 .join((forum_model.Post, forum_model.Thread.first_post)) \
50 .options(
51 contains_eager(forum_model.Thread.first_post, alias=forum_model.Post),
52 contains_eager(forum_model.Thread.first_post, forum_model.Post.thread, alias=forum_model.Thread),
53 joinedload(forum_model.Thread.first_post, forum_model.Post.author),
54 )
55
56 if max_age:
57 thread_q = thread_q.filter(forum_model.Post.posted_time >= max_age)
58
59 threads = thread_q \
60 .order_by(forum_model.Post.posted_time.desc()) \
61 [:limit]
62
63 updates = []
64 for thread in threads:
65 update = FrontPageThread(
66 source = self,
67 time = thread.first_post.posted_time,
68 post = thread.first_post,
69 )
70 updates.append(update)
71
72 return updates