Make copyright notice translatable
[aur.git] / scripts / notify.py
blobab6527727e48027b9a1f885c199f9b5f55897a9b
1 #!/usr/bin/python3
3 import configparser
4 import email.mime.text
5 import mysql.connector
6 import os
7 import smtplib
8 import subprocess
9 import sys
10 import textwrap
12 config = configparser.RawConfigParser()
13 config.read(os.path.dirname(os.path.realpath(__file__)) + '/../conf/config')
15 aur_db_host = config.get('database', 'host')
16 aur_db_name = config.get('database', 'name')
17 aur_db_user = config.get('database', 'user')
18 aur_db_pass = config.get('database', 'password')
19 aur_db_socket = config.get('database', 'socket')
21 aur_location = config.get('options', 'aur_location')
22 aur_request_ml = config.get('options', 'aur_request_ml')
24 sendmail = config.get('notifications', 'sendmail')
25 sender = config.get('notifications', 'sender')
26 reply_to = config.get('notifications', 'reply-to')
29 def headers_cc(cclist):
30 return {'Cc': str.join(', ', cclist)}
32 def headers_msgid(thread_id):
33 return {'Message-ID': thread_id}
35 def headers_reply(thread_id):
36 return {'In-Reply-To': thread_id, 'References': thread_id}
38 def send_notification(to, subject, body, refs, headers={}):
39 body = '\n'.join([textwrap.fill(line) for line in body.splitlines()])
40 body += '\n\n' + refs
42 for recipient in to:
43 msg = email.mime.text.MIMEText(body, 'plain', 'utf-8')
44 msg['Subject'] = subject
45 msg['From'] = sender
46 msg['Reply-to'] = reply_to
47 msg['To'] = recipient
49 for key, value in headers.items():
50 msg[key] = value
52 p = subprocess.Popen([sendmail, '-t', '-oi'], stdin=subprocess.PIPE)
53 p.communicate(msg.as_bytes())
55 def username_from_id(cur, uid):
56 cur.execute('SELECT UserName FROM Users WHERE ID = %s', [uid])
57 return cur.fetchone()[0]
59 def pkgbase_from_id(cur, pkgbase_id):
60 cur.execute('SELECT Name FROM PackageBases WHERE ID = %s', [pkgbase_id])
61 return cur.fetchone()[0]
63 def pkgbase_from_pkgreq(cur, reqid):
64 cur.execute('SELECT PackageBaseID FROM PackageRequests WHERE ID = %s',
65 [reqid])
66 return cur.fetchone()[0]
68 def get_maintainer_email(cur, pkgbase_id):
69 cur.execute('SELECT Users.Email FROM Users ' +
70 'INNER JOIN PackageBases ' +
71 'ON PackageBases.MaintainerUID = Users.ID WHERE ' +
72 'PackageBases.ID = %s', [pkgbase_id])
73 return cur.fetchone()[0]
75 def get_recipients(cur, pkgbase_id, uid):
76 cur.execute('SELECT DISTINCT Users.Email FROM Users ' +
77 'INNER JOIN CommentNotify ' +
78 'ON CommentNotify.UserID = Users.ID WHERE ' +
79 'CommentNotify.UserID != %s AND ' +
80 'CommentNotify.PackageBaseID = %s', [uid, pkgbase_id])
81 return [row[0] for row in cur.fetchall()]
83 def get_request_recipients(cur, pkgbase_id, uid):
84 cur.execute('SELECT DISTINCT Users.Email FROM Users ' +
85 'INNER JOIN PackageBases ' +
86 'ON PackageBases.MaintainerUID = Users.ID WHERE ' +
87 'Users.ID = %s OR PackageBases.ID = %s', [uid, pkgbase_id])
88 return [row[0] for row in cur.fetchall()]
90 def send_resetkey(cur, uid):
91 cur.execute('SELECT UserName, Email, ResetKey FROM Users WHERE ID = %s',
92 [uid])
93 username, to, resetkey = cur.fetchone()
95 subject = 'AUR Password Reset'
96 body = 'A password reset request was submitted for the account %s ' \
97 'associated with your email address. If you wish to reset your ' \
98 'password follow the link [1] below, otherwise ignore this ' \
99 'message and nothing will happen.' % (username)
100 refs = '[1] ' + aur_location + '/passreset/?resetkey=' + resetkey
102 send_notification([to], subject, body, refs)
104 def welcome(cur, uid):
105 cur.execute('SELECT UserName, Email, ResetKey FROM Users WHERE ID = %s',
106 [uid])
107 username, to, resetkey = cur.fetchone()
109 subject = 'Welcome to the Arch User Repository'
110 body = 'Welcome to the Arch User Repository! In order to set an initial ' \
111 'password for your new account, please click the link [1] below. ' \
112 'If the link does not work, try copying and pasting it into your ' \
113 'browser.'
114 refs = '[1] ' + aur_location + '/passreset/?resetkey=' + resetkey
116 send_notification([to], subject, body, refs)
118 def comment(cur, uid, pkgbase_id):
119 user = username_from_id(cur, uid)
120 pkgbase = pkgbase_from_id(cur, pkgbase_id)
121 to = get_recipients(cur, pkgbase_id, uid)
122 text = sys.stdin.read()
124 uri = aur_location + '/pkgbase/' + pkgbase + '/'
126 user_uri = aur_location + '/account/' + user + '/'
127 pkgbase_uri = aur_location + '/pkgbase/' + pkgbase + '/'
129 subject = 'AUR Comment for %s' % (pkgbase)
130 body = '%s [1] added the following comment to %s [2]:' % (user, pkgbase)
131 body += '\n\n' + text + '\n\n'
132 body += 'If you no longer wish to receive notifications about this ' \
133 'package, please go to the package page [2] and select "%s".' % \
134 ('Disable notifications')
135 refs = '[1] ' + user_uri + '\n'
136 refs += '[2] ' + pkgbase_uri
137 thread_id = '<pkg-notifications-' + pkgbase + '@aur.archlinux.org>'
138 headers = headers_reply(thread_id)
140 send_notification(to, subject, body, refs, headers)
142 def flag(cur, uid, pkgbase_id):
143 user = username_from_id(cur, uid)
144 pkgbase = pkgbase_from_id(cur, pkgbase_id)
145 to = [get_maintainer_email(cur, pkgbase_id)]
146 text = sys.stdin.read()
148 user_uri = aur_location + '/account/' + user + '/'
149 pkgbase_uri = aur_location + '/pkgbase/' + pkgbase + '/'
151 subject = 'AUR Out-of-date Notification for %s' % (pkgbase)
152 body = 'Your package %s [1] has been flagged out-of-date by %s [2]:' % \
153 (pkgbase, user)
154 body += '\n\n' + text
155 refs = '[1] ' + pkgbase_uri + '\n'
156 refs += '[2] ' + user_uri
158 send_notification(to, subject, body, refs)
160 def delete(cur, uid, old_pkgbase_id, new_pkgbase_id=None):
161 user = username_from_id(cur, uid)
162 old_pkgbase = pkgbase_from_id(cur, old_pkgbase_id)
163 if new_pkgbase_id:
164 new_pkgbase = pkgbase_from_id(cur, new_pkgbase_id)
165 to = get_recipients(cur, old_pkgbase_id, uid)
167 user_uri = aur_location + '/account/' + user + '/'
168 pkgbase_uri = aur_location + '/pkgbase/' + pkgbase + '/'
170 subject = 'AUR Package deleted: %s' % (old_pkgbase)
171 if new_pkgbase_id:
172 new_pkgbase_uri = aur_location + '/pkgbase/' + new_pkgbase + '/'
173 body = '%s [1] merged %s [2] into %s [3].\n\n' \
174 'If you no longer wish receive notifications about the new ' \
175 'package, please go to [3] and click "%s".' %\
176 (user, old_pkgbase, new_pkgbase, 'Disable notifications')
177 refs = '[1] ' + user_uri + '\n'
178 refs += '[2] ' + pkgbase_uri + '\n'
179 refs += '[3] ' + new_pkgbase_uri
180 else:
181 body = '%s [1] deleted %s [2].\n\n' \
182 'You will no longer receive notifications about this ' \
183 'package.' % (user, old_pkgbase)
184 refs = '[1] ' + user_uri + '\n'
185 refs += '[2] ' + pkgbase_uri
187 send_notification(to, subject, body, refs)
189 def request_open(cur, uid, reqid, reqtype, pkgbase_id, merge_into=None):
190 user = username_from_id(cur, uid)
191 pkgbase = pkgbase_from_id(cur, pkgbase_id)
192 to = [aur_request_ml]
193 cc = get_request_recipients(cur, pkgbase_id, uid)
194 text = sys.stdin.read()
196 user_uri = aur_location + '/account/' + user + '/'
197 pkgbase_uri = aur_location + '/pkgbase/' + pkgbase + '/'
199 subject = '[PRQ#%d] %s Request for %s' % \
200 (int(reqid), reqtype.title(), pkgbase)
201 if merge_into:
202 merge_into_uri = aur_location + '/pkgbase/' + merge_into + '/'
203 body = '%s [1] filed a request to merge %s [2] into %s [3]:' % \
204 (user, pkgbase, merge_into)
205 body += '\n\n' + text
206 refs = '[1] ' + user_uri + '\n'
207 refs += '[2] ' + pkgbase_uri + '\n'
208 refs += '[3] ' + merge_into_uri
209 else:
210 body = '%s [1] filed a %s request for %s [2]:' % \
211 (user, reqtype, pkgbase)
212 body += '\n\n' + text
213 refs = '[1] ' + user_uri + '\n'
214 refs += '[2] ' + pkgbase_uri + '\n'
215 thread_id = '<pkg-request-' + reqid + '@aur.archlinux.org>'
216 headers = headers_msgid(thread_id) + headers_cc(cc)
218 send_notification(to, subject, body, refs, headers)
220 def request_close(cur, uid, reqid, reason):
221 user = username_from_id(cur, uid)
222 pkgbase_id = pkgbase_from_pkgreq(cur, reqid)
223 to = [aur_request_ml]
224 cc = get_request_recipients(cur, pkgbase_id, uid)
225 text = sys.stdin.read()
227 user_uri = aur_location + '/account/' + user + '/'
229 subject = '[PRQ#%d] Request %s' % (int(reqid), reason.title())
230 body = 'Request #%d has been %s by %s [1]' % (int(reqid), reason, user)
231 if text.strip() == '':
232 body += '.'
233 else:
234 body += ':\n\n' + text
235 refs = '[1] ' + user_uri
236 thread_id = '<pkg-request-' + reqid + '@aur.archlinux.org>'
237 headers = headers_reply(thread_id) + headers_cc(cc)
239 send_notification(to, subject, body, refs, headers)
242 if __name__ == '__main__':
243 action = sys.argv[1]
244 action_map = {
245 'send-resetkey': send_resetkey,
246 'welcome': welcome,
247 'comment': comment,
248 'flag': flag,
249 'delete': delete,
250 'request-open': request_open,
251 'request-close': request_close,
254 db = mysql.connector.connect(host=aur_db_host, user=aur_db_user,
255 passwd=aur_db_pass, db=aur_db_name,
256 unix_socket=aur_db_socket, buffered=True)
257 cur = db.cursor()
259 action_map[action](cur, *sys.argv[2:])
261 db.commit()
262 db.close()