##// END OF EJS Templates
feeds: introduce kallithea.lib.feeds to encapsulate webhelpers.feedgenerator
Mads Kiilerich -
r7898:68e80295 default
parent child Browse files
Show More
@@ -0,0 +1,59 b''
1 # -*- coding: utf-8 -*-
2 # This program is free software: you can redistribute it and/or modify
3 # it under the terms of the GNU General Public License as published by
4 # the Free Software Foundation, either version 3 of the License, or
5 # (at your option) any later version.
6 #
7 # This program is distributed in the hope that it will be useful,
8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 # GNU General Public License for more details.
11 #
12 # You should have received a copy of the GNU General Public License
13 # along with this program. If not, see <http://www.gnu.org/licenses/>.
14
15 """
16 kallithea.lib.feeds
17 ~~~~~~~~~~~~~~~~~~~
18
19 Shared code for providing RSS and ATOM feeds.
20 """
21
22 import datetime
23 import re
24
25 from webhelpers import feedgenerator
26
27
28 language = 'en-us'
29 ttl = "5"
30
31 class _Feeder(object):
32
33 content_type = None
34 feed_factory = None # a webhelpers.feedgenerator
35
36 @classmethod
37 def render(cls, header, entries):
38 feed = cls.feed_factory(
39 language=language,
40 ttl=ttl, # rss only
41 **header
42 )
43 for e in entries:
44 feed.add_item(**e)
45 return feed.writeString('utf-8')
46
47
48 class AtomFeed(_Feeder):
49
50 content_type = 'application/atom+xml'
51
52 feed_factory = feedgenerator.Atom1Feed
53
54
55 class RssFeed(_Feeder):
56
57 content_type = 'application/rss+xml'
58
59 feed_factory = feedgenerator.Rss201rev2Feed
@@ -32,9 +32,9 b' from beaker.cache import cache_region'
32 from tg import response
32 from tg import response
33 from tg import tmpl_context as c
33 from tg import tmpl_context as c
34 from tg.i18n import ugettext as _
34 from tg.i18n import ugettext as _
35 from webhelpers.feedgenerator import Atom1Feed, Rss201rev2Feed
36
35
37 from kallithea import CONFIG
36 from kallithea import CONFIG
37 from kallithea.lib import feeds
38 from kallithea.lib import helpers as h
38 from kallithea.lib import helpers as h
39 from kallithea.lib.auth import HasRepoPermissionLevelDecorator, LoginRequired
39 from kallithea.lib.auth import HasRepoPermissionLevelDecorator, LoginRequired
40 from kallithea.lib.base import BaseRepoController
40 from kallithea.lib.base import BaseRepoController
@@ -45,10 +45,6 b' from kallithea.lib.utils2 import safe_in'
45 log = logging.getLogger(__name__)
45 log = logging.getLogger(__name__)
46
46
47
47
48 language = 'en-us'
49 ttl = "5"
50
51
52 class FeedController(BaseRepoController):
48 class FeedController(BaseRepoController):
53
49
54 @LoginRequired(allow_default_user=True)
50 @LoginRequired(allow_default_user=True)
@@ -102,39 +98,37 b' class FeedController(BaseRepoController)'
102 desc_msg.append('</pre>')
98 desc_msg.append('</pre>')
103 return [safe_unicode(chunk) for chunk in desc_msg]
99 return [safe_unicode(chunk) for chunk in desc_msg]
104
100
105 def _feed(self, repo_name, kind, feed_factory):
101 def _feed(self, repo_name, feeder):
106 """Produce a simple feed"""
102 """Produce a simple feed"""
107
103
108 @cache_region('long_term', '_get_feed_from_cache')
104 @cache_region('long_term', '_get_feed_from_cache')
109 def _get_feed_from_cache(*_cache_keys): # parameters are not really used - only as caching key
105 def _get_feed_from_cache(*_cache_keys): # parameters are not really used - only as caching key
110 feed = feed_factory(
106 header = dict(
111 title=_('%s %s feed') % (c.site_name, repo_name),
107 title=_('%s %s feed') % (c.site_name, repo_name),
112 link=h.canonical_url('summary_home', repo_name=repo_name),
108 link=h.canonical_url('summary_home', repo_name=repo_name),
113 description=_('Changes on %s repository') % repo_name,
109 description=_('Changes on %s repository') % repo_name,
114 language=language,
115 ttl=ttl, # rss only
116 )
110 )
117
111
118 rss_items_per_page = safe_int(CONFIG.get('rss_items_per_page', 20))
112 rss_items_per_page = safe_int(CONFIG.get('rss_items_per_page', 20))
113 entries=[]
119 for cs in reversed(list(c.db_repo_scm_instance[-rss_items_per_page:])):
114 for cs in reversed(list(c.db_repo_scm_instance[-rss_items_per_page:])):
120 feed.add_item(title=self._get_title(cs),
115 entries.append(dict(
121 link=h.canonical_url('changeset_home', repo_name=repo_name,
116 title=self._get_title(cs),
122 revision=cs.raw_id),
117 link=h.canonical_url('changeset_home', repo_name=repo_name, revision=cs.raw_id),
123 author_email=cs.author_email,
118 author_email=cs.author_email,
124 author_name=cs.author_name,
119 author_name=cs.author_name,
125 description=''.join(self.__get_desc(cs)),
120 description=''.join(self.__get_desc(cs)),
126 pubdate=cs.date,
121 pubdate=cs.date,
127 )
122 ))
123 return feeder.render(header, entries)
128
124
129 response.content_type = feed.mime_type
125 response.content_type = feeder.content_type
130 return feed.writeString('utf-8')
126 return _get_feed_from_cache(repo_name, feeder.__name__)
131
132 return _get_feed_from_cache(repo_name, kind, c.db_repo.changeset_cache.get('raw_id'))
133
127
134 def atom(self, repo_name):
128 def atom(self, repo_name):
135 """Produce a simple atom-1.0 feed"""
129 """Produce a simple atom-1.0 feed"""
136 return self._feed(repo_name, 'ATOM', Atom1Feed)
130 return self._feed(repo_name, feeds.AtomFeed)
137
131
138 def rss(self, repo_name):
132 def rss(self, repo_name):
139 """Produce an rss2 feed via feedgenerator module"""
133 """Produce a simple rss2 feed"""
140 return self._feed(repo_name, 'RSS', Rss201rev2Feed)
134 return self._feed(repo_name, feeds.RssFeed)
@@ -23,7 +23,6 b' Original author and date, and relevant c'
23 :author: marcink
23 :author: marcink
24 :copyright: (c) 2013 RhodeCode GmbH, and others.
24 :copyright: (c) 2013 RhodeCode GmbH, and others.
25 :license: GPLv3, see LICENSE.md for more details.
25 :license: GPLv3, see LICENSE.md for more details.
26
27 """
26 """
28
27
29 import logging
28 import logging
@@ -35,11 +34,11 b' from sqlalchemy.orm import joinedload'
35 from tg import request, response
34 from tg import request, response
36 from tg import tmpl_context as c
35 from tg import tmpl_context as c
37 from tg.i18n import ugettext as _
36 from tg.i18n import ugettext as _
38 from webhelpers.feedgenerator import Atom1Feed, Rss201rev2Feed
39 from webob.exc import HTTPBadRequest
37 from webob.exc import HTTPBadRequest
40
38
41 import kallithea.lib.helpers as h
39 import kallithea.lib.helpers as h
42 from kallithea.controllers.admin.admin import _journal_filter
40 from kallithea.controllers.admin.admin import _journal_filter
41 from kallithea.lib import feeds
43 from kallithea.lib.auth import LoginRequired
42 from kallithea.lib.auth import LoginRequired
44 from kallithea.lib.base import BaseController, render
43 from kallithea.lib.base import BaseController, render
45 from kallithea.lib.page import Page
44 from kallithea.lib.page import Page
@@ -104,17 +103,17 b' class JournalController(BaseController):'
104
103
105 return journal
104 return journal
106
105
107 def _feed(self, repos, feed_factory, link, desc):
106 def _feed(self, repos, feeder, link, desc):
107 response.content_type = feeder.content_type
108 journal = self._get_journal_data(repos)
108 journal = self._get_journal_data(repos)
109
109
110 feed = feed_factory(
110 header = dict(
111 title=desc,
111 title=desc,
112 link=link,
112 link=link,
113 description=desc,
113 description=desc,
114 language=language,
115 ttl=ttl,
116 )
114 )
117
115
116 entries=[]
118 for entry in journal[:feed_nr]:
117 for entry in journal[:feed_nr]:
119 user = entry.user
118 user = entry.user
120 if user is None:
119 if user is None:
@@ -130,15 +129,16 b' class JournalController(BaseController):'
130 _url = h.canonical_url('changelog_home',
129 _url = h.canonical_url('changelog_home',
131 repo_name=entry.repository.repo_name)
130 repo_name=entry.repository.repo_name)
132
131
133 feed.add_item(title=title,
132 entries.append(dict(
134 pubdate=entry.action_date,
133 title=title,
135 link=_url or h.canonical_url(''),
134 pubdate=entry.action_date,
136 author_email=user.email,
135 link=_url or h.canonical_url(''),
137 author_name=user.full_name_or_username,
136 author_email=user.email,
138 description=action_extra())
137 author_name=user.full_name_or_username,
138 description=action_extra(),
139 ))
139
140
140 response.content_type = feed.mime_type
141 return feeder.render(header, entries)
141 return feed.writeString('utf-8')
142
142
143 def _atom_feed(self, repos, public=True):
143 def _atom_feed(self, repos, public=True):
144 if public:
144 if public:
@@ -149,7 +149,7 b' class JournalController(BaseController):'
149 link = h.canonical_url('journal_atom')
149 link = h.canonical_url('journal_atom')
150 desc = '%s %s %s' % (c.site_name, _('Journal'), 'atom feed')
150 desc = '%s %s %s' % (c.site_name, _('Journal'), 'atom feed')
151
151
152 return self._feed(repos, Atom1Feed, link, desc)
152 return self._feed(repos, feeds.AtomFeed, link, desc)
153
153
154 def _rss_feed(self, repos, public=True):
154 def _rss_feed(self, repos, public=True):
155 if public:
155 if public:
@@ -160,7 +160,7 b' class JournalController(BaseController):'
160 link = h.canonical_url('journal_atom')
160 link = h.canonical_url('journal_atom')
161 desc = '%s %s %s' % (c.site_name, _('Journal'), 'rss feed')
161 desc = '%s %s %s' % (c.site_name, _('Journal'), 'rss feed')
162
162
163 return self._feed(repos, Rss201rev2Feed, link, desc)
163 return self._feed(repos, feeds.RssFeed, link, desc)
164
164
165 @LoginRequired()
165 @LoginRequired()
166 def index(self):
166 def index(self):
@@ -192,9 +192,7 b' class JournalController(BaseController):'
192
192
193 @LoginRequired()
193 @LoginRequired()
194 def journal_atom(self):
194 def journal_atom(self):
195 """
195 """Produce a simple atom-1.0 feed"""
196 Produce an atom-1.0 feed via feedgenerator module
197 """
198 following = UserFollowing.query() \
196 following = UserFollowing.query() \
199 .filter(UserFollowing.user_id == request.authuser.user_id) \
197 .filter(UserFollowing.user_id == request.authuser.user_id) \
200 .options(joinedload(UserFollowing.follows_repository)) \
198 .options(joinedload(UserFollowing.follows_repository)) \
@@ -203,9 +201,7 b' class JournalController(BaseController):'
203
201
204 @LoginRequired()
202 @LoginRequired()
205 def journal_rss(self):
203 def journal_rss(self):
206 """
204 """Produce a simple rss2 feed"""
207 Produce an rss feed via feedgenerator module
208 """
209 following = UserFollowing.query() \
205 following = UserFollowing.query() \
210 .filter(UserFollowing.user_id == request.authuser.user_id) \
206 .filter(UserFollowing.user_id == request.authuser.user_id) \
211 .options(joinedload(UserFollowing.follows_repository)) \
207 .options(joinedload(UserFollowing.follows_repository)) \
@@ -261,9 +257,7 b' class JournalController(BaseController):'
261
257
262 @LoginRequired(allow_default_user=True)
258 @LoginRequired(allow_default_user=True)
263 def public_journal_atom(self):
259 def public_journal_atom(self):
264 """
260 """Produce a simple atom-1.0 feed"""
265 Produce an atom-1.0 feed via feedgenerator module
266 """
267 c.following = UserFollowing.query() \
261 c.following = UserFollowing.query() \
268 .filter(UserFollowing.user_id == request.authuser.user_id) \
262 .filter(UserFollowing.user_id == request.authuser.user_id) \
269 .options(joinedload(UserFollowing.follows_repository)) \
263 .options(joinedload(UserFollowing.follows_repository)) \
@@ -273,9 +267,7 b' class JournalController(BaseController):'
273
267
274 @LoginRequired(allow_default_user=True)
268 @LoginRequired(allow_default_user=True)
275 def public_journal_rss(self):
269 def public_journal_rss(self):
276 """
270 """Produce a simple rss2 feed"""
277 Produce an rss2 feed via feedgenerator module
278 """
279 c.following = UserFollowing.query() \
271 c.following = UserFollowing.query() \
280 .filter(UserFollowing.user_id == request.authuser.user_id) \
272 .filter(UserFollowing.user_id == request.authuser.user_id) \
281 .options(joinedload(UserFollowing.follows_repository)) \
273 .options(joinedload(UserFollowing.follows_repository)) \
General Comments 0
You need to be logged in to leave comments. Login now