##// END OF EJS Templates
fixed kwargs ->email_kwargs
marcink -
r2814:5acab314 beta
parent child Browse files
Show More
@@ -1,241 +1,241 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 rhodecode.model.comment
3 rhodecode.model.comment
4 ~~~~~~~~~~~~~~~~~~~~~~~
4 ~~~~~~~~~~~~~~~~~~~~~~~
5
5
6 comments model for RhodeCode
6 comments model for RhodeCode
7
7
8 :created_on: Nov 11, 2011
8 :created_on: Nov 11, 2011
9 :author: marcink
9 :author: marcink
10 :copyright: (C) 2011-2012 Marcin Kuzminski <marcin@python-works.com>
10 :copyright: (C) 2011-2012 Marcin Kuzminski <marcin@python-works.com>
11 :license: GPLv3, see COPYING for more details.
11 :license: GPLv3, see COPYING for more details.
12 """
12 """
13 # This program is free software: you can redistribute it and/or modify
13 # This program is free software: you can redistribute it and/or modify
14 # it under the terms of the GNU General Public License as published by
14 # it under the terms of the GNU General Public License as published by
15 # the Free Software Foundation, either version 3 of the License, or
15 # the Free Software Foundation, either version 3 of the License, or
16 # (at your option) any later version.
16 # (at your option) any later version.
17 #
17 #
18 # This program is distributed in the hope that it will be useful,
18 # This program is distributed in the hope that it will be useful,
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 # GNU General Public License for more details.
21 # GNU General Public License for more details.
22 #
22 #
23 # You should have received a copy of the GNU General Public License
23 # You should have received a copy of the GNU General Public License
24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
25
25
26 import logging
26 import logging
27 import traceback
27 import traceback
28
28
29 from pylons.i18n.translation import _
29 from pylons.i18n.translation import _
30 from sqlalchemy.util.compat import defaultdict
30 from sqlalchemy.util.compat import defaultdict
31
31
32 from rhodecode.lib.utils2 import extract_mentioned_users, safe_unicode
32 from rhodecode.lib.utils2 import extract_mentioned_users, safe_unicode
33 from rhodecode.lib import helpers as h
33 from rhodecode.lib import helpers as h
34 from rhodecode.model import BaseModel
34 from rhodecode.model import BaseModel
35 from rhodecode.model.db import ChangesetComment, User, Repository, \
35 from rhodecode.model.db import ChangesetComment, User, Repository, \
36 Notification, PullRequest
36 Notification, PullRequest
37 from rhodecode.model.notification import NotificationModel
37 from rhodecode.model.notification import NotificationModel
38
38
39 log = logging.getLogger(__name__)
39 log = logging.getLogger(__name__)
40
40
41
41
42 class ChangesetCommentsModel(BaseModel):
42 class ChangesetCommentsModel(BaseModel):
43
43
44 cls = ChangesetComment
44 cls = ChangesetComment
45
45
46 def __get_changeset_comment(self, changeset_comment):
46 def __get_changeset_comment(self, changeset_comment):
47 return self._get_instance(ChangesetComment, changeset_comment)
47 return self._get_instance(ChangesetComment, changeset_comment)
48
48
49 def __get_pull_request(self, pull_request):
49 def __get_pull_request(self, pull_request):
50 return self._get_instance(PullRequest, pull_request)
50 return self._get_instance(PullRequest, pull_request)
51
51
52 def _extract_mentions(self, s):
52 def _extract_mentions(self, s):
53 user_objects = []
53 user_objects = []
54 for username in extract_mentioned_users(s):
54 for username in extract_mentioned_users(s):
55 user_obj = User.get_by_username(username, case_insensitive=True)
55 user_obj = User.get_by_username(username, case_insensitive=True)
56 if user_obj:
56 if user_obj:
57 user_objects.append(user_obj)
57 user_objects.append(user_obj)
58 return user_objects
58 return user_objects
59
59
60 def create(self, text, repo, user, revision=None, pull_request=None,
60 def create(self, text, repo, user, revision=None, pull_request=None,
61 f_path=None, line_no=None, status_change=None):
61 f_path=None, line_no=None, status_change=None):
62 """
62 """
63 Creates new comment for changeset or pull request.
63 Creates new comment for changeset or pull request.
64 IF status_change is not none this comment is associated with a
64 IF status_change is not none this comment is associated with a
65 status change of changeset or changesets associated with pull request
65 status change of changeset or changesets associated with pull request
66
66
67 :param text:
67 :param text:
68 :param repo:
68 :param repo:
69 :param user:
69 :param user:
70 :param revision:
70 :param revision:
71 :param pull_request:
71 :param pull_request:
72 :param f_path:
72 :param f_path:
73 :param line_no:
73 :param line_no:
74 :param status_change:
74 :param status_change:
75 """
75 """
76 if not text:
76 if not text:
77 return
77 return
78
78
79 repo = self._get_repo(repo)
79 repo = self._get_repo(repo)
80 user = self._get_user(user)
80 user = self._get_user(user)
81 comment = ChangesetComment()
81 comment = ChangesetComment()
82 comment.repo = repo
82 comment.repo = repo
83 comment.author = user
83 comment.author = user
84 comment.text = text
84 comment.text = text
85 comment.f_path = f_path
85 comment.f_path = f_path
86 comment.line_no = line_no
86 comment.line_no = line_no
87
87
88 if revision:
88 if revision:
89 cs = repo.scm_instance.get_changeset(revision)
89 cs = repo.scm_instance.get_changeset(revision)
90 desc = "%s - %s" % (cs.short_id, h.shorter(cs.message, 256))
90 desc = "%s - %s" % (cs.short_id, h.shorter(cs.message, 256))
91 author_email = cs.author_email
91 author_email = cs.author_email
92 comment.revision = revision
92 comment.revision = revision
93 elif pull_request:
93 elif pull_request:
94 pull_request = self.__get_pull_request(pull_request)
94 pull_request = self.__get_pull_request(pull_request)
95 comment.pull_request = pull_request
95 comment.pull_request = pull_request
96 desc = pull_request.pull_request_id
96 desc = pull_request.pull_request_id
97 else:
97 else:
98 raise Exception('Please specify revision or pull_request_id')
98 raise Exception('Please specify revision or pull_request_id')
99
99
100 self.sa.add(comment)
100 self.sa.add(comment)
101 self.sa.flush()
101 self.sa.flush()
102
102
103 # make notification
103 # make notification
104 line = ''
104 line = ''
105 body = text
105 body = text
106
106
107 #changeset
107 #changeset
108 if revision:
108 if revision:
109 if line_no:
109 if line_no:
110 line = _('on line %s') % line_no
110 line = _('on line %s') % line_no
111 subj = safe_unicode(
111 subj = safe_unicode(
112 h.link_to('Re commit: %(desc)s %(line)s' % \
112 h.link_to('Re commit: %(desc)s %(line)s' % \
113 {'desc': desc, 'line': line},
113 {'desc': desc, 'line': line},
114 h.url('changeset_home', repo_name=repo.repo_name,
114 h.url('changeset_home', repo_name=repo.repo_name,
115 revision=revision,
115 revision=revision,
116 anchor='comment-%s' % comment.comment_id,
116 anchor='comment-%s' % comment.comment_id,
117 qualified=True,
117 qualified=True,
118 )
118 )
119 )
119 )
120 )
120 )
121 notification_type = Notification.TYPE_CHANGESET_COMMENT
121 notification_type = Notification.TYPE_CHANGESET_COMMENT
122 # get the current participants of this changeset
122 # get the current participants of this changeset
123 recipients = ChangesetComment.get_users(revision=revision)
123 recipients = ChangesetComment.get_users(revision=revision)
124 # add changeset author if it's in rhodecode system
124 # add changeset author if it's in rhodecode system
125 recipients += [User.get_by_email(author_email)]
125 recipients += [User.get_by_email(author_email)]
126 email_kwargs = {
126 email_kwargs = {
127 'status_change': status_change,
127 'status_change': status_change,
128 }
128 }
129 #pull request
129 #pull request
130 elif pull_request:
130 elif pull_request:
131 _url = h.url('pullrequest_show',
131 _url = h.url('pullrequest_show',
132 repo_name=pull_request.other_repo.repo_name,
132 repo_name=pull_request.other_repo.repo_name,
133 pull_request_id=pull_request.pull_request_id,
133 pull_request_id=pull_request.pull_request_id,
134 anchor='comment-%s' % comment.comment_id,
134 anchor='comment-%s' % comment.comment_id,
135 qualified=True,
135 qualified=True,
136 )
136 )
137 subj = safe_unicode(
137 subj = safe_unicode(
138 h.link_to('Re pull request: %(desc)s %(line)s' % \
138 h.link_to('Re pull request: %(desc)s %(line)s' % \
139 {'desc': desc, 'line': line}, _url)
139 {'desc': desc, 'line': line}, _url)
140 )
140 )
141
141
142 notification_type = Notification.TYPE_PULL_REQUEST_COMMENT
142 notification_type = Notification.TYPE_PULL_REQUEST_COMMENT
143 # get the current participants of this pull request
143 # get the current participants of this pull request
144 recipients = ChangesetComment.get_users(pull_request_id=
144 recipients = ChangesetComment.get_users(pull_request_id=
145 pull_request.pull_request_id)
145 pull_request.pull_request_id)
146 # add pull request author
146 # add pull request author
147 recipients += [pull_request.author]
147 recipients += [pull_request.author]
148
148
149 # add the reviewers to notification
149 # add the reviewers to notification
150 recipients += [x.user for x in pull_request.reviewers]
150 recipients += [x.user for x in pull_request.reviewers]
151
151
152 #set some variables for email notification
152 #set some variables for email notification
153 email_kwargs = {
153 email_kwargs = {
154 'pr_id': pull_request.pull_request_id,
154 'pr_id': pull_request.pull_request_id,
155 'status_change': status_change,
155 'status_change': status_change,
156 'pr_comment_url': _url,
156 'pr_comment_url': _url,
157 'pr_comment_user': h.person(user.email),
157 'pr_comment_user': h.person(user.email),
158 'pr_target_repo': h.url('summary_home',
158 'pr_target_repo': h.url('summary_home',
159 repo_name=pull_request.other_repo.repo_name,
159 repo_name=pull_request.other_repo.repo_name,
160 qualified=True)
160 qualified=True)
161 }
161 }
162 # create notification objects, and emails
162 # create notification objects, and emails
163 NotificationModel().create(
163 NotificationModel().create(
164 created_by=user, subject=subj, body=body,
164 created_by=user, subject=subj, body=body,
165 recipients=recipients, type_=notification_type,
165 recipients=recipients, type_=notification_type,
166 email_kwargs=email_kwargs
166 email_kwargs=email_kwargs
167 )
167 )
168
168
169 mention_recipients = set(self._extract_mentions(body))\
169 mention_recipients = set(self._extract_mentions(body))\
170 .difference(recipients)
170 .difference(recipients)
171 if mention_recipients:
171 if mention_recipients:
172 kwargs.update({'pr_mention': True})
172 email_kwargs.update({'pr_mention': True})
173 subj = _('[Mention]') + ' ' + subj
173 subj = _('[Mention]') + ' ' + subj
174 NotificationModel().create(
174 NotificationModel().create(
175 created_by=user, subject=subj, body=body,
175 created_by=user, subject=subj, body=body,
176 recipients=mention_recipients,
176 recipients=mention_recipients,
177 type_=notification_type,
177 type_=notification_type,
178 email_kwargs=kwargs
178 email_kwargs=email_kwargs
179 )
179 )
180
180
181 return comment
181 return comment
182
182
183 def delete(self, comment):
183 def delete(self, comment):
184 """
184 """
185 Deletes given comment
185 Deletes given comment
186
186
187 :param comment_id:
187 :param comment_id:
188 """
188 """
189 comment = self.__get_changeset_comment(comment)
189 comment = self.__get_changeset_comment(comment)
190 self.sa.delete(comment)
190 self.sa.delete(comment)
191
191
192 return comment
192 return comment
193
193
194 def get_comments(self, repo_id, revision=None, pull_request=None):
194 def get_comments(self, repo_id, revision=None, pull_request=None):
195 """
195 """
196 Get's main comments based on revision or pull_request_id
196 Get's main comments based on revision or pull_request_id
197
197
198 :param repo_id:
198 :param repo_id:
199 :type repo_id:
199 :type repo_id:
200 :param revision:
200 :param revision:
201 :type revision:
201 :type revision:
202 :param pull_request:
202 :param pull_request:
203 :type pull_request:
203 :type pull_request:
204 """
204 """
205
205
206 q = ChangesetComment.query()\
206 q = ChangesetComment.query()\
207 .filter(ChangesetComment.repo_id == repo_id)\
207 .filter(ChangesetComment.repo_id == repo_id)\
208 .filter(ChangesetComment.line_no == None)\
208 .filter(ChangesetComment.line_no == None)\
209 .filter(ChangesetComment.f_path == None)
209 .filter(ChangesetComment.f_path == None)
210 if revision:
210 if revision:
211 q = q.filter(ChangesetComment.revision == revision)
211 q = q.filter(ChangesetComment.revision == revision)
212 elif pull_request:
212 elif pull_request:
213 pull_request = self.__get_pull_request(pull_request)
213 pull_request = self.__get_pull_request(pull_request)
214 q = q.filter(ChangesetComment.pull_request == pull_request)
214 q = q.filter(ChangesetComment.pull_request == pull_request)
215 else:
215 else:
216 raise Exception('Please specify revision or pull_request')
216 raise Exception('Please specify revision or pull_request')
217 q = q.order_by(ChangesetComment.created_on)
217 q = q.order_by(ChangesetComment.created_on)
218 return q.all()
218 return q.all()
219
219
220 def get_inline_comments(self, repo_id, revision=None, pull_request=None):
220 def get_inline_comments(self, repo_id, revision=None, pull_request=None):
221 q = self.sa.query(ChangesetComment)\
221 q = self.sa.query(ChangesetComment)\
222 .filter(ChangesetComment.repo_id == repo_id)\
222 .filter(ChangesetComment.repo_id == repo_id)\
223 .filter(ChangesetComment.line_no != None)\
223 .filter(ChangesetComment.line_no != None)\
224 .filter(ChangesetComment.f_path != None)\
224 .filter(ChangesetComment.f_path != None)\
225 .order_by(ChangesetComment.comment_id.asc())\
225 .order_by(ChangesetComment.comment_id.asc())\
226
226
227 if revision:
227 if revision:
228 q = q.filter(ChangesetComment.revision == revision)
228 q = q.filter(ChangesetComment.revision == revision)
229 elif pull_request:
229 elif pull_request:
230 pull_request = self.__get_pull_request(pull_request)
230 pull_request = self.__get_pull_request(pull_request)
231 q = q.filter(ChangesetComment.pull_request == pull_request)
231 q = q.filter(ChangesetComment.pull_request == pull_request)
232 else:
232 else:
233 raise Exception('Please specify revision or pull_request_id')
233 raise Exception('Please specify revision or pull_request_id')
234
234
235 comments = q.all()
235 comments = q.all()
236
236
237 paths = defaultdict(lambda: defaultdict(list))
237 paths = defaultdict(lambda: defaultdict(list))
238
238
239 for co in comments:
239 for co in comments:
240 paths[co.f_path][co.line_no].append(co)
240 paths[co.f_path][co.line_no].append(co)
241 return paths.items()
241 return paths.items()
General Comments 0
You need to be logged in to leave comments. Login now