Show More
@@ -1,127 +1,222 b'' | |||
|
1 | 1 | # -*- coding: utf-8 -*- |
|
2 | 2 | |
|
3 | 3 | # Copyright (C) 2012-2016 RhodeCode GmbH |
|
4 | 4 | # |
|
5 | 5 | # This program is free software: you can redistribute it and/or modify |
|
6 | 6 | # it under the terms of the GNU Affero General Public License, version 3 |
|
7 | 7 | # (only), as published by the Free Software Foundation. |
|
8 | 8 | # |
|
9 | 9 | # This program is distributed in the hope that it will be useful, |
|
10 | 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 | 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
12 | 12 | # GNU General Public License for more details. |
|
13 | 13 | # |
|
14 | 14 | # You should have received a copy of the GNU Affero General Public License |
|
15 | 15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
16 | 16 | # |
|
17 | 17 | # This program is dual-licensed. If you wish to learn more about the |
|
18 | 18 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
19 | 19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
20 | 20 | |
|
21 | 21 | from __future__ import unicode_literals |
|
22 | ||
|
23 | 22 | import deform |
|
24 | 23 | import logging |
|
25 | 24 | import colander |
|
26 | 25 | |
|
27 | 26 | from mako.template import Template |
|
28 | 27 | |
|
29 | 28 | from rhodecode import events |
|
30 | 29 | from rhodecode.translation import _, lazy_ugettext |
|
31 | 30 | from rhodecode.lib.celerylib import run_task |
|
32 | 31 | from rhodecode.lib.celerylib import tasks |
|
33 | 32 | from rhodecode.integrations.types.base import IntegrationTypeBase |
|
34 | 33 | from rhodecode.integrations.schema import IntegrationSettingsSchemaBase |
|
35 | 34 | |
|
36 | 35 | |
|
37 | log = logging.getLogger() | |
|
36 | log = logging.getLogger(__name__) | |
|
37 | ||
|
38 | repo_push_template_plaintext = Template(''' | |
|
39 | Commits: | |
|
40 | ||
|
41 | % for commit in data['push']['commits']: | |
|
42 | ${commit['url']} by ${commit['author']} at ${commit['date']} | |
|
43 | ${commit['message']} | |
|
44 | ---- | |
|
45 | ||
|
46 | % endfor | |
|
47 | ''') | |
|
48 | ||
|
49 | ## TODO (marcink): think about putting this into a file, or use base.mako email template | |
|
50 | ||
|
51 | repo_push_template_html = Template(''' | |
|
52 | <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> | |
|
53 | <html xmlns="http://www.w3.org/1999/xhtml"> | |
|
54 | <head> | |
|
55 | <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> | |
|
56 | <meta name="viewport" content="width=device-width, initial-scale=1.0"/> | |
|
57 | <title>${subject}</title> | |
|
58 | <style type="text/css"> | |
|
59 | /* Based on The MailChimp Reset INLINE: Yes. */ | |
|
60 | #outlook a {padding:0;} /* Force Outlook to provide a "view in browser" menu link. */ | |
|
61 | body{width:100% !important; -webkit-text-size-adjust:100%; -ms-text-size-adjust:100%; margin:0; padding:0;} | |
|
62 | /* Prevent Webkit and Windows Mobile platforms from changing default font sizes.*/ | |
|
63 | .ExternalClass {width:100%;} /* Force Hotmail to display emails at full width */ | |
|
64 | .ExternalClass, .ExternalClass p, .ExternalClass span, .ExternalClass font, .ExternalClass td, .ExternalClass div {line-height: 100%;} | |
|
65 | /* Forces Hotmail to display normal line spacing. More on that: http://www.emailonacid.com/forum/viewthread/43/ */ | |
|
66 | #backgroundTable {margin:0; padding:0; line-height: 100% !important;} | |
|
67 | /* End reset */ | |
|
68 | ||
|
69 | /* defaults for images*/ | |
|
70 | img {outline:none; text-decoration:none; -ms-interpolation-mode: bicubic;} | |
|
71 | a img {border:none;} | |
|
72 | .image_fix {display:block;} | |
|
73 | ||
|
74 | body {line-height:1.2em;} | |
|
75 | p {margin: 0 0 20px;} | |
|
76 | h1, h2, h3, h4, h5, h6 {color:#323232!important;} | |
|
77 | a {color:#427cc9;text-decoration:none;outline:none;cursor:pointer;} | |
|
78 | a:focus {outline:none;} | |
|
79 | a:hover {color: #305b91;} | |
|
80 | h1 a, h2 a, h3 a, h4 a, h5 a, h6 a {color:#427cc9!important;text-decoration:none!important;} | |
|
81 | h1 a:active, h2 a:active, h3 a:active, h4 a:active, h5 a:active, h6 a:active {color: #305b91!important;} | |
|
82 | h1 a:visited, h2 a:visited, h3 a:visited, h4 a:visited, h5 a:visited, h6 a:visited {color: #305b91!important;} | |
|
83 | table {font-size:13px;border-collapse:collapse;mso-table-lspace:0pt;mso-table-rspace:0pt;} | |
|
84 | table td {padding:.65em 1em .65em 0;border-collapse:collapse;vertical-align:top;text-align:left;} | |
|
85 | input {display:inline;border-radius:2px;border-style:solid;border: 1px solid #dbd9da;padding:.5em;} | |
|
86 | input:focus {outline: 1px solid #979797} | |
|
87 | @media only screen and (-webkit-min-device-pixel-ratio: 2) { | |
|
88 | /* Put your iPhone 4g styles in here */ | |
|
89 | } | |
|
38 | 90 | |
|
91 | /* Android targeting */ | |
|
92 | @media only screen and (-webkit-device-pixel-ratio:.75){ | |
|
93 | /* Put CSS for low density (ldpi) Android layouts in here */ | |
|
94 | } | |
|
95 | @media only screen and (-webkit-device-pixel-ratio:1){ | |
|
96 | /* Put CSS for medium density (mdpi) Android layouts in here */ | |
|
97 | } | |
|
98 | @media only screen and (-webkit-device-pixel-ratio:1.5){ | |
|
99 | /* Put CSS for high density (hdpi) Android layouts in here */ | |
|
100 | } | |
|
101 | /* end Android targeting */ | |
|
102 | ||
|
103 | </style> | |
|
104 | ||
|
105 | <!-- Targeting Windows Mobile --> | |
|
106 | <!--[if IEMobile 7]> | |
|
107 | <style type="text/css"> | |
|
108 | ||
|
109 | </style> | |
|
110 | <![endif]--> | |
|
111 | ||
|
112 | <!--[if gte mso 9]> | |
|
113 | <style> | |
|
114 | /* Target Outlook 2007 and 2010 */ | |
|
115 | </style> | |
|
116 | <![endif]--> | |
|
117 | </head> | |
|
118 | <body> | |
|
119 | <!-- Wrapper/Container Table: Use a wrapper table to control the width and the background color consistently of your email. Use this approach instead of setting attributes on the body tag. --> | |
|
120 | <table cellpadding="0" cellspacing="0" border="0" id="backgroundTable" align="left" style="margin:1%;width:97%;padding:0;font-family:sans-serif;font-weight:100;border:1px solid #dbd9da"> | |
|
121 | <tr> | |
|
122 | <td valign="top" style="padding:0;"> | |
|
123 | <table cellpadding="0" cellspacing="0" border="0" align="left" width="100%"> | |
|
124 | <tr><td style="width:100%;padding:7px;background-color:#202020" valign="top"> | |
|
125 | <a style="color:#eeeeee;text-decoration:none;" href="${instance_url}"> | |
|
126 | ${'RhodeCode'} | |
|
127 | </a> | |
|
128 | </td></tr> | |
|
129 | <tr> | |
|
130 | <td style="padding:15px;" valign="top"> | |
|
131 | % for commit in data['push']['commits']: | |
|
132 | <a href="${commit['url']}">${commit['short_id']}</a> by ${commit['author']} at ${commit['date']} <br/> | |
|
133 | ${commit['message_html']} <br/> | |
|
134 | <br/> | |
|
135 | % endfor | |
|
136 | </td> | |
|
137 | </tr> | |
|
138 | </table> | |
|
139 | </td> | |
|
140 | </tr> | |
|
141 | </table> | |
|
142 | <!-- End of wrapper table --> | |
|
143 | <p><a style="margin-top:15px;margin-left:1%;font-family:sans-serif;font-weight:100;font-size:11px;color:#666666;text-decoration:none;" href="${instance_url}"> | |
|
144 | ${'This is a notification from RhodeCode. %(instance_url)s' % {'instance_url': instance_url}} | |
|
145 | </a></p> | |
|
146 | </body> | |
|
147 | </html> | |
|
148 | ''') | |
|
39 | 149 | |
|
40 | 150 | |
|
41 | 151 | class EmailSettingsSchema(IntegrationSettingsSchemaBase): |
|
42 | 152 | @colander.instantiate(validator=colander.Length(min=1)) |
|
43 | 153 | class recipients(colander.SequenceSchema): |
|
44 | 154 | title = lazy_ugettext('Recipients') |
|
45 | 155 | description = lazy_ugettext('Email addresses to send push events to') |
|
46 | 156 | widget = deform.widget.SequenceWidget(min_len=1) |
|
47 | 157 | |
|
48 | 158 | recipient = colander.SchemaNode( |
|
49 | 159 | colander.String(), |
|
50 | 160 | title=lazy_ugettext('Email address'), |
|
51 | 161 | description=lazy_ugettext('Email address'), |
|
52 | 162 | default='', |
|
53 | 163 | validator=colander.Email(), |
|
54 | 164 | widget=deform.widget.TextInputWidget( |
|
55 | 165 | placeholder='user@domain.com', |
|
56 | 166 | ), |
|
57 | 167 | ) |
|
58 | 168 | |
|
59 | 169 | |
|
60 | 170 | class EmailIntegrationType(IntegrationTypeBase): |
|
61 | 171 | key = 'email' |
|
62 | 172 | display_name = lazy_ugettext('Email') |
|
63 | 173 | SettingsSchema = EmailSettingsSchema |
|
64 | 174 | |
|
65 | 175 | def settings_schema(self): |
|
66 | 176 | schema = EmailSettingsSchema() |
|
67 | 177 | return schema |
|
68 | 178 | |
|
69 | 179 | def send_event(self, event): |
|
70 | 180 | data = event.as_dict() |
|
71 | 181 | log.debug('got event: %r', event) |
|
72 | 182 | |
|
73 | 183 | if isinstance(event, events.RepoPushEvent): |
|
74 | 184 | repo_push_handler(data, self.settings) |
|
75 | 185 | else: |
|
76 | 186 | log.debug('ignoring event: %r', event) |
|
77 | 187 | |
|
78 | 188 | |
|
79 | 189 | def repo_push_handler(data, settings): |
|
80 |
|
|
|
190 | commit_num = len(data['push']['commits']) | |
|
191 | server_url = data['server_url'] | |
|
192 | ||
|
193 | if commit_num == 0: | |
|
194 | subject = '[{repo_name}] {author} pushed {commit_num} commit on branches: {branches}'.format( | |
|
195 | author=data['actor']['username'], | |
|
196 | repo_name=data['repo']['repo_name'], | |
|
197 | commit_num=commit_num, | |
|
198 | branches=', '.join( | |
|
199 | branch['name'] for branch in data['push']['branches']) | |
|
200 | ) | |
|
201 | else: | |
|
202 | subject = '[{repo_name}] {author} pushed {commit_num} commits on branches: {branches}'.format( | |
|
203 | author=data['actor']['username'], | |
|
204 | repo_name=data['repo']['repo_name'], | |
|
205 | commit_num=commit_num, | |
|
206 | branches=', '.join( | |
|
207 | branch['name'] for branch in data['push']['branches'])) | |
|
208 | ||
|
81 | 209 |
|
|
82 | 210 |
|
|
83 | commit=commit, | |
|
84 | commit_msg=commit['message'], | |
|
85 | ) | |
|
211 | subject=subject, | |
|
212 | instance_url=server_url) | |
|
213 | ||
|
86 | 214 |
|
|
87 | 215 |
|
|
88 | commit=commit, | |
|
89 | commit_msg=commit['message_html'], | |
|
90 | ) | |
|
216 | subject=subject, | |
|
217 | instance_url=server_url) | |
|
91 | 218 | |
|
92 | subject = '[%(repo_name)s] %(commit_id)s: %(commit_msg)s' % { | |
|
93 | 'repo_name': data['repo']['repo_name'], | |
|
94 | 'commit_id': commit['short_id'], | |
|
95 | 'commit_msg': commit['message'].split('\n')[0][:150] | |
|
96 | } | |
|
97 | 219 |
|
|
98 |
|
|
|
220 | run_task( | |
|
99 | 221 |
|
|
100 | 222 |
|
|
101 | ||
|
102 | ||
|
103 | # TODO: dan: add changed files, make html pretty | |
|
104 | repo_push_template_plaintext = Template(''' | |
|
105 | User: ${data['actor']['username']} | |
|
106 | Branches: ${', '.join(branch['name'] for branch in data['push']['branches'])} | |
|
107 | Repository: ${data['repo']['url']} | |
|
108 | Commit: ${commit['raw_id']} | |
|
109 | URL: ${commit['url']} | |
|
110 | Author: ${commit['author']} | |
|
111 | Date: ${commit['date']} | |
|
112 | Commit Message: | |
|
113 | ||
|
114 | ${commit_msg} | |
|
115 | ''') | |
|
116 | ||
|
117 | repo_push_template_html = Template(''' | |
|
118 | User: ${data['actor']['username']}<br> | |
|
119 | Branches: ${', '.join(branch['name'] for branch in data['push']['branches'])}<br> | |
|
120 | Repository: ${data['repo']['url']}<br> | |
|
121 | Commit: ${commit['raw_id']}<br> | |
|
122 | URL: ${commit['url']}<br> | |
|
123 | Author: ${commit['author']}<br> | |
|
124 | Date: ${commit['date']}<br> | |
|
125 | Commit Message:<br> | |
|
126 | <p>${commit_msg}</p> | |
|
127 | ''') |
General Comments 0
You need to be logged in to leave comments.
Login now