##// END OF EJS Templates
added template context into Notification templates
marcink -
r3423:043d3827 beta
parent child Browse files
Show More
@@ -1,278 +1,280 b''
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 rhodecode.model.notification
4 4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 5
6 6 Model for notifications
7 7
8 8
9 9 :created_on: Nov 20, 2011
10 10 :author: marcink
11 11 :copyright: (C) 2010-2012 Marcin Kuzminski <marcin@python-works.com>
12 12 :license: GPLv3, see COPYING for more details.
13 13 """
14 14 # This program is free software: you can redistribute it and/or modify
15 15 # it under the terms of the GNU General Public License as published by
16 16 # the Free Software Foundation, either version 3 of the License, or
17 17 # (at your option) any later version.
18 18 #
19 19 # This program is distributed in the hope that it will be useful,
20 20 # but WITHOUT ANY WARRANTY; without even the implied warranty of
21 21 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 22 # GNU General Public License for more details.
23 23 #
24 24 # You should have received a copy of the GNU General Public License
25 25 # along with this program. If not, see <http://www.gnu.org/licenses/>.
26 26
27 27 import os
28 28 import logging
29 29 import traceback
30 30
31 from pylons import tmpl_context as c
31 32 from pylons.i18n.translation import _
32 33
33 34 import rhodecode
34 35 from rhodecode.lib import helpers as h
35 36 from rhodecode.model import BaseModel
36 37 from rhodecode.model.db import Notification, User, UserNotification
37 38
38 39 log = logging.getLogger(__name__)
39 40
40 41
41 42 class NotificationModel(BaseModel):
42 43
43 44 cls = Notification
44 45
45 46 def __get_notification(self, notification):
46 47 if isinstance(notification, Notification):
47 48 return notification
48 49 elif isinstance(notification, (int, long)):
49 50 return Notification.get(notification)
50 51 else:
51 52 if notification:
52 53 raise Exception('notification must be int, long or Instance'
53 54 ' of Notification got %s' % type(notification))
54 55
55 56 def create(self, created_by, subject, body, recipients=None,
56 57 type_=Notification.TYPE_MESSAGE, with_email=True,
57 58 email_kwargs={}):
58 59 """
59 60
60 61 Creates notification of given type
61 62
62 63 :param created_by: int, str or User instance. User who created this
63 64 notification
64 65 :param subject:
65 66 :param body:
66 67 :param recipients: list of int, str or User objects, when None
67 68 is given send to all admins
68 69 :param type_: type of notification
69 70 :param with_email: send email with this notification
70 71 :param email_kwargs: additional dict to pass as args to email template
71 72 """
72 73 from rhodecode.lib.celerylib import tasks, run_task
73 74
74 75 if recipients and not getattr(recipients, '__iter__', False):
75 76 raise Exception('recipients must be a list or iterable')
76 77
77 78 created_by_obj = self._get_user(created_by)
78 79
79 80 if recipients:
80 81 recipients_objs = []
81 82 for u in recipients:
82 83 obj = self._get_user(u)
83 84 if obj:
84 85 recipients_objs.append(obj)
85 86 recipients_objs = set(recipients_objs)
86 87 log.debug('sending notifications %s to %s' % (
87 88 type_, recipients_objs)
88 89 )
89 90 else:
90 91 # empty recipients means to all admins
91 92 recipients_objs = User.query().filter(User.admin == True).all()
92 93 log.debug('sending notifications %s to admins: %s' % (
93 94 type_, recipients_objs)
94 95 )
95 96 notif = Notification.create(
96 97 created_by=created_by_obj, subject=subject,
97 98 body=body, recipients=recipients_objs, type_=type_
98 99 )
99 100
100 101 if with_email is False:
101 102 return notif
102 103
103 104 #don't send email to person who created this comment
104 105 rec_objs = set(recipients_objs).difference(set([created_by_obj]))
105 106
106 107 # send email with notification to all other participants
107 108 for rec in rec_objs:
108 109 email_subject = NotificationModel().make_description(notif, False)
109 110 type_ = type_
110 111 email_body = body
111 112 ## this is passed into template
112 113 kwargs = {'subject': subject, 'body': h.rst_w_mentions(body)}
113 114 kwargs.update(email_kwargs)
114 115 email_body_html = EmailNotificationModel()\
115 116 .get_email_tmpl(type_, **kwargs)
116 117
117 118 run_task(tasks.send_email, rec.email, email_subject, email_body,
118 119 email_body_html)
119 120
120 121 return notif
121 122
122 123 def delete(self, user, notification):
123 124 # we don't want to remove actual notification just the assignment
124 125 try:
125 126 notification = self.__get_notification(notification)
126 127 user = self._get_user(user)
127 128 if notification and user:
128 129 obj = UserNotification.query()\
129 130 .filter(UserNotification.user == user)\
130 131 .filter(UserNotification.notification
131 132 == notification)\
132 133 .one()
133 134 self.sa.delete(obj)
134 135 return True
135 136 except Exception:
136 137 log.error(traceback.format_exc())
137 138 raise
138 139
139 140 def get_for_user(self, user, filter_=None):
140 141 """
141 142 Get mentions for given user, filter them if filter dict is given
142 143
143 144 :param user:
144 145 :type user:
145 146 :param filter:
146 147 """
147 148 user = self._get_user(user)
148 149
149 150 q = UserNotification.query()\
150 151 .filter(UserNotification.user == user)\
151 152 .join((Notification, UserNotification.notification_id ==
152 153 Notification.notification_id))
153 154
154 155 if filter_:
155 156 q = q.filter(Notification.type_.in_(filter_))
156 157
157 158 return q.all()
158 159
159 160 def mark_read(self, user, notification):
160 161 try:
161 162 notification = self.__get_notification(notification)
162 163 user = self._get_user(user)
163 164 if notification and user:
164 165 obj = UserNotification.query()\
165 166 .filter(UserNotification.user == user)\
166 167 .filter(UserNotification.notification
167 168 == notification)\
168 169 .one()
169 170 obj.read = True
170 171 self.sa.add(obj)
171 172 return True
172 173 except Exception:
173 174 log.error(traceback.format_exc())
174 175 raise
175 176
176 177 def mark_all_read_for_user(self, user, filter_=None):
177 178 user = self._get_user(user)
178 179 q = UserNotification.query()\
179 180 .filter(UserNotification.user == user)\
180 181 .filter(UserNotification.read == False)\
181 182 .join((Notification, UserNotification.notification_id ==
182 183 Notification.notification_id))
183 184 if filter_:
184 185 q = q.filter(Notification.type_.in_(filter_))
185 186
186 187 # this is a little inefficient but sqlalchemy doesn't support
187 188 # update on joined tables :(
188 189 for obj in q.all():
189 190 obj.read = True
190 191 self.sa.add(obj)
191 192
192 193 def get_unread_cnt_for_user(self, user):
193 194 user = self._get_user(user)
194 195 return UserNotification.query()\
195 196 .filter(UserNotification.read == False)\
196 197 .filter(UserNotification.user == user).count()
197 198
198 199 def get_unread_for_user(self, user):
199 200 user = self._get_user(user)
200 201 return [x.notification for x in UserNotification.query()\
201 202 .filter(UserNotification.read == False)\
202 203 .filter(UserNotification.user == user).all()]
203 204
204 205 def get_user_notification(self, user, notification):
205 206 user = self._get_user(user)
206 207 notification = self.__get_notification(notification)
207 208
208 209 return UserNotification.query()\
209 210 .filter(UserNotification.notification == notification)\
210 211 .filter(UserNotification.user == user).scalar()
211 212
212 213 def make_description(self, notification, show_age=True):
213 214 """
214 215 Creates a human readable description based on properties
215 216 of notification object
216 217 """
217 218 #alias
218 219 _n = notification
219 220 _map = {
220 221 _n.TYPE_CHANGESET_COMMENT: _('commented on commit at %(when)s'),
221 222 _n.TYPE_MESSAGE: _('sent message at %(when)s'),
222 223 _n.TYPE_MENTION: _('mentioned you at %(when)s'),
223 224 _n.TYPE_REGISTRATION: _('registered in RhodeCode at %(when)s'),
224 225 _n.TYPE_PULL_REQUEST: _('opened new pull request at %(when)s'),
225 226 _n.TYPE_PULL_REQUEST_COMMENT: _('commented on pull request at %(when)s')
226 227 }
227 228
228 229 # action == _map string
229 230 tmpl = "%(user)s %(action)s "
230 231 if show_age:
231 232 when = h.age(notification.created_on)
232 233 else:
233 234 when = h.fmt_date(notification.created_on)
234 235
235 236 data = dict(
236 237 user=notification.created_by_user.username,
237 238 action=_map[notification.type_] % {'when': when},
238 239 )
239 240 return tmpl % data
240 241
241 242
242 243 class EmailNotificationModel(BaseModel):
243 244
244 245 TYPE_CHANGESET_COMMENT = Notification.TYPE_CHANGESET_COMMENT
245 246 TYPE_PASSWORD_RESET = 'password_link'
246 247 TYPE_REGISTRATION = Notification.TYPE_REGISTRATION
247 248 TYPE_PULL_REQUEST = Notification.TYPE_PULL_REQUEST
248 249 TYPE_PULL_REQUEST_COMMENT = Notification.TYPE_PULL_REQUEST_COMMENT
249 250 TYPE_DEFAULT = 'default'
250 251
251 252 def __init__(self):
252 253 self._template_root = rhodecode.CONFIG['pylons.paths']['templates'][0]
253 254 self._tmpl_lookup = rhodecode.CONFIG['pylons.app_globals'].mako_lookup
254 255
255 256 self.email_types = {
256 257 self.TYPE_CHANGESET_COMMENT: 'email_templates/changeset_comment.html',
257 258 self.TYPE_PASSWORD_RESET: 'email_templates/password_reset.html',
258 259 self.TYPE_REGISTRATION: 'email_templates/registration.html',
259 260 self.TYPE_DEFAULT: 'email_templates/default.html',
260 261 self.TYPE_PULL_REQUEST: 'email_templates/pull_request.html',
261 262 self.TYPE_PULL_REQUEST_COMMENT: 'email_templates/pull_request_comment.html',
262 263 }
263 264
264 265 def get_email_tmpl(self, type_, **kwargs):
265 266 """
266 267 return generated template for email based on given type
267 268
268 269 :param type_:
269 270 """
270 271
271 272 base = self.email_types.get(type_, self.email_types[self.TYPE_DEFAULT])
272 273 email_template = self._tmpl_lookup.get_template(base)
273 274 # translator and helpers inject
274 275 _kwargs = {'_': _,
275 'h': h}
276 'h': h,
277 'c': c}
276 278 _kwargs.update(kwargs)
277 279 log.debug('rendering tmpl %s with kwargs %s' % (base, _kwargs))
278 280 return email_template.render(**_kwargs)
General Comments 0
You need to be logged in to leave comments. Login now