mirror of
https://gitlab.archlinux.org/archlinux/aurweb.git
synced 2025-02-03 10:43:03 +01:00
Refactor the notification script
Reimplement most of the notification script logic. Create a separate class for each notification type. Each class provides methods for generating the list of recipients, the message subject, the message body, the references to add at the end of the message and the message headers. Additionally, a method for sending notification emails is provided. One major benefit of the new implementation is that both the generation of recipients and message contents are much more flexible. For example, it is now easily possible to make user-specific adjustments to every single notification of a batch. Signed-off-by: Lukas Fleischer <lfleischer@archlinux.org>
This commit is contained in:
parent
fec253a65d
commit
f3b4c5c6bc
1 changed files with 429 additions and 393 deletions
|
@ -9,11 +9,6 @@ import aurweb.config
|
||||||
import aurweb.db
|
import aurweb.db
|
||||||
|
|
||||||
aur_location = aurweb.config.get('options', 'aur_location')
|
aur_location = aurweb.config.get('options', 'aur_location')
|
||||||
aur_request_ml = aurweb.config.get('options', 'aur_request_ml')
|
|
||||||
|
|
||||||
sendmail = aurweb.config.get('notifications', 'sendmail')
|
|
||||||
sender = aurweb.config.get('notifications', 'sender')
|
|
||||||
reply_to = aurweb.config.get('notifications', 'reply-to')
|
|
||||||
|
|
||||||
|
|
||||||
def headers_cc(cclist):
|
def headers_cc(cclist):
|
||||||
|
@ -28,29 +23,6 @@ def headers_reply(thread_id):
|
||||||
return {'In-Reply-To': thread_id, 'References': thread_id}
|
return {'In-Reply-To': thread_id, 'References': thread_id}
|
||||||
|
|
||||||
|
|
||||||
def send_notification(to, subject, body, refs, headers={}):
|
|
||||||
wrapped = ''
|
|
||||||
for line in body.splitlines():
|
|
||||||
wrapped += textwrap.fill(line, break_long_words=False) + '\n'
|
|
||||||
if refs:
|
|
||||||
body = wrapped + '\n' + refs
|
|
||||||
else:
|
|
||||||
body = wrapped.rstrip()
|
|
||||||
|
|
||||||
for recipient in to:
|
|
||||||
msg = email.mime.text.MIMEText(body, 'plain', 'utf-8')
|
|
||||||
msg['Subject'] = subject
|
|
||||||
msg['From'] = sender
|
|
||||||
msg['Reply-to'] = reply_to
|
|
||||||
msg['To'] = recipient
|
|
||||||
|
|
||||||
for key, value in headers.items():
|
|
||||||
msg[key] = value
|
|
||||||
|
|
||||||
p = subprocess.Popen([sendmail, '-t', '-oi'], stdin=subprocess.PIPE)
|
|
||||||
p.communicate(msg.as_bytes())
|
|
||||||
|
|
||||||
|
|
||||||
def username_from_id(conn, uid):
|
def username_from_id(conn, uid):
|
||||||
cur = conn.execute('SELECT UserName FROM Users WHERE ID = ?', [uid])
|
cur = conn.execute('SELECT UserName FROM Users WHERE ID = ?', [uid])
|
||||||
return cur.fetchone()[0]
|
return cur.fetchone()[0]
|
||||||
|
@ -73,380 +45,444 @@ def get_user_email(conn, uid):
|
||||||
return cur.fetchone()[0]
|
return cur.fetchone()[0]
|
||||||
|
|
||||||
|
|
||||||
def get_flag_recipients(conn, pkgbase_id):
|
class Notification:
|
||||||
cur = conn.execute('SELECT DISTINCT Users.Email FROM Users ' +
|
def get_refs(self):
|
||||||
'LEFT JOIN PackageComaintainers ' +
|
return ()
|
||||||
'ON PackageComaintainers.UsersID = Users.ID ' +
|
|
||||||
'INNER JOIN PackageBases ' +
|
def get_headers(self):
|
||||||
'ON PackageBases.MaintainerUID = Users.ID OR ' +
|
return {}
|
||||||
'PackageBases.ID = PackageComaintainers.PackageBaseID ' +
|
|
||||||
'WHERE PackageBases.ID = ?', [pkgbase_id])
|
def send(self):
|
||||||
return [row[0] for row in cur.fetchall()]
|
body = ''
|
||||||
|
for line in self.get_body().splitlines():
|
||||||
|
body += textwrap.fill(line, break_long_words=False) + '\n'
|
||||||
def get_recipients(conn, pkgbase_id, uid):
|
for i, ref in enumerate(self.get_refs()):
|
||||||
cur = conn.execute('SELECT DISTINCT Users.Email FROM Users ' +
|
body += '\n' + '[%d] %s' % (i + 1, ref)
|
||||||
'INNER JOIN PackageNotifications ' +
|
body = body.rstrip()
|
||||||
'ON PackageNotifications.UserID = Users.ID WHERE ' +
|
|
||||||
'PackageNotifications.UserID != ? AND ' +
|
sendmail = aurweb.config.get('notifications', 'sendmail')
|
||||||
'PackageNotifications.PackageBaseID = ?',
|
sender = aurweb.config.get('notifications', 'sender')
|
||||||
[uid, pkgbase_id])
|
reply_to = aurweb.config.get('notifications', 'reply-to')
|
||||||
return [row[0] for row in cur.fetchall()]
|
|
||||||
|
for recipient in self.get_recipients():
|
||||||
|
msg = email.mime.text.MIMEText(body, 'plain', 'utf-8')
|
||||||
def get_comment_recipients(conn, pkgbase_id, uid):
|
msg['Subject'] = self.get_subject()
|
||||||
cur = conn.execute('SELECT DISTINCT Users.Email FROM Users ' +
|
msg['From'] = sender
|
||||||
'INNER JOIN PackageNotifications ' +
|
msg['Reply-to'] = reply_to
|
||||||
'ON PackageNotifications.UserID = Users.ID WHERE ' +
|
msg['To'] = recipient
|
||||||
'Users.CommentNotify = 1 AND ' +
|
|
||||||
'PackageNotifications.UserID != ? AND ' +
|
for key, value in self.get_headers().items():
|
||||||
'PackageNotifications.PackageBaseID = ?',
|
msg[key] = value
|
||||||
[uid, pkgbase_id])
|
|
||||||
return [row[0] for row in cur.fetchall()]
|
p = subprocess.Popen([sendmail, '-t', '-oi'],
|
||||||
|
stdin=subprocess.PIPE)
|
||||||
|
p.communicate(msg.as_bytes())
|
||||||
def get_update_recipients(conn, pkgbase_id, uid):
|
|
||||||
cur = conn.execute('SELECT DISTINCT Users.Email FROM Users ' +
|
|
||||||
'INNER JOIN PackageNotifications ' +
|
class ResetKeyNotification(Notification):
|
||||||
'ON PackageNotifications.UserID = Users.ID WHERE ' +
|
def __init__(self, conn, uid):
|
||||||
'Users.UpdateNotify = 1 AND ' +
|
cur = conn.execute('SELECT UserName, Email, ResetKey FROM Users ' +
|
||||||
'PackageNotifications.UserID != ? AND ' +
|
'WHERE ID = ?', [uid])
|
||||||
'PackageNotifications.PackageBaseID = ?',
|
self._username, self._to, self._resetkey = cur.fetchone()
|
||||||
[uid, pkgbase_id])
|
|
||||||
return [row[0] for row in cur.fetchall()]
|
def get_recipients(self):
|
||||||
|
return [self._to]
|
||||||
|
|
||||||
def get_ownership_recipients(conn, pkgbase_id, uid):
|
def get_subject(self):
|
||||||
cur = conn.execute('SELECT DISTINCT Users.Email FROM Users ' +
|
return 'AUR Password Reset'
|
||||||
'INNER JOIN PackageNotifications ' +
|
|
||||||
'ON PackageNotifications.UserID = Users.ID WHERE ' +
|
def get_body(self):
|
||||||
'Users.OwnershipNotify = 1 AND ' +
|
return 'A password reset request was submitted for the account %s ' \
|
||||||
'PackageNotifications.UserID != ? AND ' +
|
'associated with your email address. If you wish to reset ' \
|
||||||
'PackageNotifications.PackageBaseID = ?',
|
'your password follow the link [1] below, otherwise ignore ' \
|
||||||
[uid, pkgbase_id])
|
'this message and nothing will happen.' % (self._username)
|
||||||
return [row[0] for row in cur.fetchall()]
|
|
||||||
|
def get_refs(self):
|
||||||
|
return (aur_location + '/passreset/?resetkey=' + self._resetkey,)
|
||||||
def get_request_recipients(conn, reqid):
|
|
||||||
cur = conn.execute('SELECT DISTINCT Users.Email FROM PackageRequests ' +
|
|
||||||
'INNER JOIN PackageBases ' +
|
class WelcomeNotification(ResetKeyNotification):
|
||||||
'ON PackageBases.ID = PackageRequests.PackageBaseID ' +
|
def get_subject(self):
|
||||||
'INNER JOIN Users ' +
|
return 'Welcome to the Arch User Repository'
|
||||||
'ON Users.ID = PackageRequests.UsersID ' +
|
|
||||||
'OR Users.ID = PackageBases.MaintainerUID ' +
|
def get_body(self):
|
||||||
'WHERE PackageRequests.ID = ?', [reqid])
|
return 'Welcome to the Arch User Repository! In order to set an ' \
|
||||||
return [row[0] for row in cur.fetchall()]
|
'initial password for your new account, please click the ' \
|
||||||
|
'link [1] below. If the link does not work, try copying and ' \
|
||||||
|
'pasting it into your browser.'
|
||||||
def get_tu_vote_reminder_recipients(conn, vote_id):
|
|
||||||
cur = conn.execute('SELECT Email FROM Users ' +
|
|
||||||
'WHERE AccountTypeID IN (2, 4) AND ID NOT IN ' +
|
class CommentNotification(Notification):
|
||||||
'(SELECT UserID FROM TU_Votes ' +
|
def __init__(self, conn, uid, pkgbase_id, comment_id):
|
||||||
'WHERE TU_Votes.VoteID = ?)', [vote_id])
|
self._user = username_from_id(conn, uid)
|
||||||
return [row[0] for row in cur.fetchall()]
|
self._pkgbase = pkgbase_from_id(conn, pkgbase_id)
|
||||||
|
cur = conn.execute('SELECT DISTINCT Users.Email FROM Users ' +
|
||||||
|
'INNER JOIN PackageNotifications ' +
|
||||||
def get_comment(conn, comment_id):
|
'ON PackageNotifications.UserID = Users.ID WHERE ' +
|
||||||
cur = conn.execute('SELECT Comments FROM PackageComments WHERE ID = ?',
|
'Users.CommentNotify = 1 AND ' +
|
||||||
[comment_id])
|
'PackageNotifications.UserID != ? AND ' +
|
||||||
return cur.fetchone()[0]
|
'PackageNotifications.PackageBaseID = ?',
|
||||||
|
[uid, pkgbase_id])
|
||||||
|
self._to = [row[0] for row in cur.fetchall()]
|
||||||
def get_flagger_comment(conn, pkgbase_id):
|
cur = conn.execute('SELECT Comments FROM PackageComments WHERE ID = ?',
|
||||||
cur = conn.execute('SELECT FlaggerComment FROM PackageBases WHERE ID = ?',
|
[comment_id])
|
||||||
[pkgbase_id])
|
self._text = cur.fetchone()[0]
|
||||||
return cur.fetchone()[0]
|
|
||||||
|
def get_recipients(self):
|
||||||
|
return self._to
|
||||||
def get_request_comment(conn, reqid):
|
|
||||||
cur = conn.execute('SELECT Comments FROM PackageRequests WHERE ID = ?',
|
def get_subject(self):
|
||||||
[reqid])
|
return 'AUR Comment for %s' % (self._pkgbase)
|
||||||
return cur.fetchone()[0]
|
|
||||||
|
def get_body(self):
|
||||||
|
body = '%s [1] added the following comment to %s [2]:' % \
|
||||||
def get_request_closure_comment(conn, reqid):
|
(self._user, self._pkgbase)
|
||||||
cur = conn.execute('SELECT ClosureComment FROM PackageRequests ' +
|
body += '\n\n' + self._text + '\n\n'
|
||||||
'WHERE ID = ?', [reqid])
|
body += 'If you no longer wish to receive notifications about this ' \
|
||||||
return cur.fetchone()[0]
|
'package, please go to the package page [2] and select ' \
|
||||||
|
'"%s".' % ('Disable notifications')
|
||||||
|
return body
|
||||||
def send_resetkey(conn, uid):
|
|
||||||
cur = conn.execute('SELECT UserName, Email, ResetKey FROM Users ' +
|
def get_refs(self):
|
||||||
'WHERE ID = ?', [uid])
|
return (aur_location + '/account/' + self._user + '/',
|
||||||
username, to, resetkey = cur.fetchone()
|
aur_location + '/pkgbase/' + self._pkgbase + '/')
|
||||||
|
|
||||||
subject = 'AUR Password Reset'
|
def get_headers(self):
|
||||||
body = 'A password reset request was submitted for the account %s ' \
|
thread_id = '<pkg-notifications-' + self._pkgbase + \
|
||||||
'associated with your email address. If you wish to reset your ' \
|
'@aur.archlinux.org>'
|
||||||
'password follow the link [1] below, otherwise ignore this ' \
|
return headers_reply(thread_id)
|
||||||
'message and nothing will happen.' % (username)
|
|
||||||
refs = '[1] ' + aur_location + '/passreset/?resetkey=' + resetkey
|
|
||||||
|
class UpdateNotification(Notification):
|
||||||
send_notification([to], subject, body, refs)
|
def __init__(self, conn, uid, pkgbase_id):
|
||||||
|
self._user = username_from_id(conn, uid)
|
||||||
|
self._pkgbase = pkgbase_from_id(conn, pkgbase_id)
|
||||||
def welcome(conn, uid):
|
cur = conn.execute('SELECT DISTINCT Users.Email FROM Users ' +
|
||||||
cur = conn.execute('SELECT UserName, Email, ResetKey FROM Users ' +
|
'INNER JOIN PackageNotifications ' +
|
||||||
'WHERE ID = ?', [uid])
|
'ON PackageNotifications.UserID = Users.ID WHERE ' +
|
||||||
username, to, resetkey = cur.fetchone()
|
'Users.UpdateNotify = 1 AND ' +
|
||||||
|
'PackageNotifications.UserID != ? AND ' +
|
||||||
subject = 'Welcome to the Arch User Repository'
|
'PackageNotifications.PackageBaseID = ?',
|
||||||
body = 'Welcome to the Arch User Repository! In order to set an initial ' \
|
[uid, pkgbase_id])
|
||||||
'password for your new account, please click the link [1] below. ' \
|
self._to = [row[0] for row in cur.fetchall()]
|
||||||
'If the link does not work, try copying and pasting it into your ' \
|
|
||||||
'browser.'
|
def get_recipients(self):
|
||||||
refs = '[1] ' + aur_location + '/passreset/?resetkey=' + resetkey
|
return self._to
|
||||||
|
|
||||||
send_notification([to], subject, body, refs)
|
def get_subject(self):
|
||||||
|
return 'AUR Package Update: %s' % (self._pkgbase)
|
||||||
|
|
||||||
def comment(conn, uid, pkgbase_id, comment_id):
|
def get_body(self):
|
||||||
user = username_from_id(conn, uid)
|
body = '%s [1] pushed a new commit to %s [2].' % \
|
||||||
pkgbase = pkgbase_from_id(conn, pkgbase_id)
|
(self._user, self._pkgbase)
|
||||||
to = get_comment_recipients(conn, pkgbase_id, uid)
|
body += '\n\n'
|
||||||
text = get_comment(conn, comment_id)
|
body += 'If you no longer wish to receive notifications about this ' \
|
||||||
|
'package, please go to the package page [2] and select ' \
|
||||||
user_uri = aur_location + '/account/' + user + '/'
|
'"%s".' % ('Disable notifications')
|
||||||
pkgbase_uri = aur_location + '/pkgbase/' + pkgbase + '/'
|
return body
|
||||||
|
|
||||||
subject = 'AUR Comment for %s' % (pkgbase)
|
def get_refs(self):
|
||||||
body = '%s [1] added the following comment to %s [2]:' % (user, pkgbase)
|
return (aur_location + '/account/' + self._user + '/',
|
||||||
body += '\n\n' + text + '\n\n'
|
aur_location + '/pkgbase/' + self._pkgbase + '/')
|
||||||
body += 'If you no longer wish to receive notifications about this ' \
|
|
||||||
'package, please go to the package page [2] and select "%s".' % \
|
def get_headers(self):
|
||||||
('Disable notifications')
|
thread_id = '<pkg-notifications-' + self._pkgbase + \
|
||||||
refs = '[1] ' + user_uri + '\n'
|
'@aur.archlinux.org>'
|
||||||
refs += '[2] ' + pkgbase_uri
|
return headers_reply(thread_id)
|
||||||
thread_id = '<pkg-notifications-' + pkgbase + '@aur.archlinux.org>'
|
|
||||||
headers = headers_reply(thread_id)
|
|
||||||
|
class FlagNotification(Notification):
|
||||||
send_notification(to, subject, body, refs, headers)
|
def __init__(self, conn, uid, pkgbase_id):
|
||||||
|
self._user = username_from_id(conn, uid)
|
||||||
|
self._pkgbase = pkgbase_from_id(conn, pkgbase_id)
|
||||||
def update(conn, uid, pkgbase_id):
|
cur = conn.execute('SELECT DISTINCT Users.Email FROM Users ' +
|
||||||
user = username_from_id(conn, uid)
|
'LEFT JOIN PackageComaintainers ' +
|
||||||
pkgbase = pkgbase_from_id(conn, pkgbase_id)
|
'ON PackageComaintainers.UsersID = Users.ID ' +
|
||||||
to = get_update_recipients(conn, pkgbase_id, uid)
|
'INNER JOIN PackageBases ' +
|
||||||
|
'ON PackageBases.MaintainerUID = Users.ID OR ' +
|
||||||
user_uri = aur_location + '/account/' + user + '/'
|
'PackageBases.ID = PackageComaintainers.PackageBaseID ' +
|
||||||
pkgbase_uri = aur_location + '/pkgbase/' + pkgbase + '/'
|
'WHERE PackageBases.ID = ?', [pkgbase_id])
|
||||||
|
self._to = [row[0] for row in cur.fetchall()]
|
||||||
subject = 'AUR Package Update: %s' % (pkgbase)
|
cur = conn.execute('SELECT FlaggerComment FROM PackageBases WHERE ' +
|
||||||
body = '%s [1] pushed a new commit to %s [2].' % (user, pkgbase)
|
'ID = ?', [pkgbase_id])
|
||||||
body += '\n\n'
|
self._text = cur.fetchone()[0]
|
||||||
body += 'If you no longer wish to receive notifications about this ' \
|
|
||||||
'package, please go to the package page [2] and select "%s".' % \
|
def get_recipients(self):
|
||||||
('Disable notifications')
|
return self._to
|
||||||
refs = '[1] ' + user_uri + '\n'
|
|
||||||
refs += '[2] ' + pkgbase_uri
|
def get_subject(self):
|
||||||
thread_id = '<pkg-notifications-' + pkgbase + '@aur.archlinux.org>'
|
return 'AUR Out-of-date Notification for %s' % (self._pkgbase)
|
||||||
headers = headers_reply(thread_id)
|
|
||||||
|
def get_body(self):
|
||||||
send_notification(to, subject, body, refs, headers)
|
body = 'Your package %s [1] has been flagged out-of-date by ' \
|
||||||
|
'%s [2]:' % (self._pkgbase, self._user)
|
||||||
|
body += '\n\n' + self._text
|
||||||
def flag(conn, uid, pkgbase_id):
|
return body
|
||||||
user = username_from_id(conn, uid)
|
|
||||||
pkgbase = pkgbase_from_id(conn, pkgbase_id)
|
def get_refs(self):
|
||||||
to = get_flag_recipients(conn, pkgbase_id)
|
return (aur_location + '/pkgbase/' + self._pkgbase + '/',
|
||||||
text = get_flagger_comment(conn, pkgbase_id)
|
aur_location + '/account/' + self._user + '/')
|
||||||
|
|
||||||
user_uri = aur_location + '/account/' + user + '/'
|
|
||||||
pkgbase_uri = aur_location + '/pkgbase/' + pkgbase + '/'
|
class OwnershipEventNotification(Notification):
|
||||||
|
def __init__(self, conn, uid, pkgbase_id):
|
||||||
subject = 'AUR Out-of-date Notification for %s' % (pkgbase)
|
self._user = username_from_id(conn, uid)
|
||||||
body = 'Your package %s [1] has been flagged out-of-date by %s [2]:' % \
|
self._pkgbase = pkgbase_from_id(conn, pkgbase_id)
|
||||||
(pkgbase, user)
|
cur = conn.execute('SELECT DISTINCT Users.Email FROM Users ' +
|
||||||
body += '\n\n' + text
|
'INNER JOIN PackageNotifications ' +
|
||||||
refs = '[1] ' + pkgbase_uri + '\n'
|
'ON PackageNotifications.UserID = Users.ID WHERE ' +
|
||||||
refs += '[2] ' + user_uri
|
'Users.OwnershipNotify = 1 AND ' +
|
||||||
|
'PackageNotifications.UserID != ? AND ' +
|
||||||
send_notification(to, subject, body, refs)
|
'PackageNotifications.PackageBaseID = ?',
|
||||||
|
[uid, pkgbase_id])
|
||||||
|
self._to = [row[0] for row in cur.fetchall()]
|
||||||
def adopt(conn, pkgbase_id, uid):
|
cur = conn.execute('SELECT FlaggerComment FROM PackageBases WHERE ' +
|
||||||
user = username_from_id(conn, uid)
|
'ID = ?', [pkgbase_id])
|
||||||
pkgbase = pkgbase_from_id(conn, pkgbase_id)
|
self._text = cur.fetchone()[0]
|
||||||
to = get_ownership_recipients(conn, pkgbase_id, uid)
|
|
||||||
|
def get_recipients(self):
|
||||||
user_uri = aur_location + '/account/' + user + '/'
|
return self._to
|
||||||
pkgbase_uri = aur_location + '/pkgbase/' + pkgbase + '/'
|
|
||||||
|
def get_subject(self):
|
||||||
subject = 'AUR Ownership Notification for %s' % (pkgbase)
|
return 'AUR Ownership Notification for %s' % (self._pkgbase)
|
||||||
body = 'The package %s [1] was adopted by %s [2].' % (pkgbase, user)
|
|
||||||
refs = '[1] ' + pkgbase_uri + '\n'
|
def get_refs(self):
|
||||||
refs += '[2] ' + user_uri
|
return (aur_location + '/pkgbase/' + self._pkgbase + '/',
|
||||||
|
aur_location + '/account/' + self._user + '/')
|
||||||
send_notification(to, subject, body, refs)
|
|
||||||
|
|
||||||
|
class AdoptNotification(OwnershipEventNotification):
|
||||||
def disown(conn, pkgbase_id, uid):
|
def get_body(self):
|
||||||
user = username_from_id(conn, uid)
|
return 'The package %s [1] was adopted by %s [2].' % \
|
||||||
pkgbase = pkgbase_from_id(conn, pkgbase_id)
|
(self._pkgbase, self._user)
|
||||||
to = get_ownership_recipients(conn, pkgbase_id, uid)
|
|
||||||
|
|
||||||
user_uri = aur_location + '/account/' + user + '/'
|
class DisownNotification(OwnershipEventNotification):
|
||||||
pkgbase_uri = aur_location + '/pkgbase/' + pkgbase + '/'
|
def get_body(self):
|
||||||
|
return 'The package %s [1] was disowned by %s [2].' % \
|
||||||
subject = 'AUR Ownership Notification for %s' % (pkgbase)
|
(self._pkgbase, self._user)
|
||||||
body = 'The package %s [1] was disowned by %s [2].' % (pkgbase, user)
|
|
||||||
refs = '[1] ' + pkgbase_uri + '\n'
|
|
||||||
refs += '[2] ' + user_uri
|
class ComaintainershipEventNotification(Notification):
|
||||||
|
def __init__(self, conn, uid, pkgbase_id):
|
||||||
send_notification(to, subject, body, refs)
|
self._pkgbase = pkgbase_from_id(conn, pkgbase_id)
|
||||||
|
self._to = get_user_email(conn, uid)
|
||||||
|
|
||||||
def comaintainer_add(conn, pkgbase_id, uid):
|
def get_recipients(self):
|
||||||
pkgbase = pkgbase_from_id(conn, pkgbase_id)
|
return [self._to]
|
||||||
to = [get_user_email(conn, uid)]
|
|
||||||
|
def get_subject(self):
|
||||||
pkgbase_uri = aur_location + '/pkgbase/' + pkgbase + '/'
|
return 'AUR Co-Maintainer Notification for %s' % (self._pkgbase)
|
||||||
|
|
||||||
subject = 'AUR Co-Maintainer Notification for %s' % (pkgbase)
|
def get_refs(self):
|
||||||
body = 'You were added to the co-maintainer list of %s [1].' % (pkgbase)
|
return (aur_location + '/pkgbase/' + self._pkgbase + '/',)
|
||||||
refs = '[1] ' + pkgbase_uri
|
|
||||||
|
|
||||||
send_notification(to, subject, body, refs)
|
class ComaintainerAddNotification(ComaintainershipEventNotification):
|
||||||
|
def get_body(self):
|
||||||
|
return 'You were added to the co-maintainer list of %s [1].' % \
|
||||||
def comaintainer_remove(conn, pkgbase_id, uid):
|
(self._pkgbase)
|
||||||
pkgbase = pkgbase_from_id(conn, pkgbase_id)
|
|
||||||
to = [get_user_email(conn, uid)]
|
|
||||||
|
class ComaintainerRemoveNotification(ComaintainershipEventNotification):
|
||||||
pkgbase_uri = aur_location + '/pkgbase/' + pkgbase + '/'
|
def get_body(self):
|
||||||
|
return 'You were removed from the co-maintainer list of %s [1].' % \
|
||||||
subject = 'AUR Co-Maintainer Notification for %s' % (pkgbase)
|
(self._pkgbase)
|
||||||
body = ('You were removed from the co-maintainer list of %s [1].' %
|
|
||||||
(pkgbase))
|
|
||||||
refs = '[1] ' + pkgbase_uri
|
class DeleteNotification(Notification):
|
||||||
|
def __init__(self, conn, uid, old_pkgbase_id, new_pkgbase_id=None):
|
||||||
send_notification(to, subject, body, refs)
|
self._user = username_from_id(conn, uid)
|
||||||
|
self._old_pkgbase = pkgbase_from_id(conn, old_pkgbase_id)
|
||||||
|
if new_pkgbase_id:
|
||||||
def delete(conn, uid, old_pkgbase_id, new_pkgbase_id=None):
|
self._new_pkgbase = pkgbase_from_id(conn, new_pkgbase_id)
|
||||||
user = username_from_id(conn, uid)
|
else:
|
||||||
old_pkgbase = pkgbase_from_id(conn, old_pkgbase_id)
|
self._new_pkgbase = None
|
||||||
if new_pkgbase_id:
|
cur = conn.execute('SELECT DISTINCT Users.Email FROM Users ' +
|
||||||
new_pkgbase = pkgbase_from_id(conn, new_pkgbase_id)
|
'INNER JOIN PackageNotifications ' +
|
||||||
to = get_recipients(conn, old_pkgbase_id, uid)
|
'ON PackageNotifications.UserID = Users.ID WHERE ' +
|
||||||
|
'PackageNotifications.UserID != ? AND ' +
|
||||||
user_uri = aur_location + '/account/' + user + '/'
|
'PackageNotifications.PackageBaseID = ?',
|
||||||
pkgbase_uri = aur_location + '/pkgbase/' + old_pkgbase + '/'
|
[uid, old_pkgbase_id])
|
||||||
|
self._to = [row[0] for row in cur.fetchall()]
|
||||||
subject = 'AUR Package deleted: %s' % (old_pkgbase)
|
|
||||||
if new_pkgbase_id:
|
def get_recipients(self):
|
||||||
new_pkgbase_uri = aur_location + '/pkgbase/' + new_pkgbase + '/'
|
return self._to
|
||||||
body = '%s [1] merged %s [2] into %s [3].\n\n' \
|
|
||||||
'If you no longer wish receive notifications about the new ' \
|
def get_subject(self):
|
||||||
'package, please go to [3] and click "%s".' %\
|
return 'AUR Package deleted: %s' % (self._old_pkgbase)
|
||||||
(user, old_pkgbase, new_pkgbase, 'Disable notifications')
|
|
||||||
refs = '[1] ' + user_uri + '\n'
|
def get_body(self):
|
||||||
refs += '[2] ' + pkgbase_uri + '\n'
|
if self._new_pkgbase:
|
||||||
refs += '[3] ' + new_pkgbase_uri
|
return '%s [1] merged %s [2] into %s [3].\n\n' \
|
||||||
else:
|
'If you no longer wish receive notifications about the ' \
|
||||||
body = '%s [1] deleted %s [2].\n\n' \
|
'new package, please go to [3] and click "%s".' % \
|
||||||
'You will no longer receive notifications about this ' \
|
(self._user, self._old_pkgbase, self._new_pkgbase,
|
||||||
'package.' % (user, old_pkgbase)
|
'Disable notifications')
|
||||||
refs = '[1] ' + user_uri + '\n'
|
else:
|
||||||
refs += '[2] ' + pkgbase_uri
|
return '%s [1] deleted %s [2].\n\n' \
|
||||||
|
'You will no longer receive notifications about this ' \
|
||||||
send_notification(to, subject, body, refs)
|
'package.' % (self._user, self._old_pkgbase)
|
||||||
|
|
||||||
|
def get_refs(self):
|
||||||
def request_open(conn, uid, reqid, reqtype, pkgbase_id, merge_into=None):
|
refs = (aur_location + '/account/' + self._user + '/',
|
||||||
user = username_from_id(conn, uid)
|
aur_location + '/pkgbase/' + self._old_pkgbase + '/')
|
||||||
pkgbase = pkgbase_from_id(conn, pkgbase_id)
|
if self._new_pkgbase:
|
||||||
to = [aur_request_ml]
|
refs += (aur_location + '/pkgbase/' + self._new_pkgbase + '/',)
|
||||||
cc = get_request_recipients(conn, reqid)
|
return refs
|
||||||
text = get_request_comment(conn, reqid)
|
|
||||||
|
|
||||||
user_uri = aur_location + '/account/' + user + '/'
|
class RequestOpenNotification(Notification):
|
||||||
pkgbase_uri = aur_location + '/pkgbase/' + pkgbase + '/'
|
def __init__(self, conn, uid, reqid, reqtype, pkgbase_id, merge_into=None):
|
||||||
|
self._user = username_from_id(conn, uid)
|
||||||
subject = '[PRQ#%d] %s Request for %s' % \
|
self._pkgbase = pkgbase_from_id(conn, pkgbase_id)
|
||||||
(int(reqid), reqtype.title(), pkgbase)
|
cur = conn.execute('SELECT DISTINCT Users.Email FROM PackageRequests ' +
|
||||||
if merge_into:
|
'INNER JOIN PackageBases ' +
|
||||||
merge_into_uri = aur_location + '/pkgbase/' + merge_into + '/'
|
'ON PackageBases.ID = PackageRequests.PackageBaseID ' +
|
||||||
body = '%s [1] filed a request to merge %s [2] into %s [3]:' % \
|
'INNER JOIN Users ' +
|
||||||
(user, pkgbase, merge_into)
|
'ON Users.ID = PackageRequests.UsersID ' +
|
||||||
body += '\n\n' + text
|
'OR Users.ID = PackageBases.MaintainerUID ' +
|
||||||
refs = '[1] ' + user_uri + '\n'
|
'WHERE PackageRequests.ID = ?', [reqid])
|
||||||
refs += '[2] ' + pkgbase_uri + '\n'
|
self._to = aurweb.config.get('options', 'aur_request_ml')
|
||||||
refs += '[3] ' + merge_into_uri
|
self._cc = [row[0] for row in cur.fetchall()]
|
||||||
else:
|
cur = conn.execute('SELECT Comments FROM PackageRequests WHERE ID = ?',
|
||||||
body = '%s [1] filed a %s request for %s [2]:' % \
|
[reqid])
|
||||||
(user, reqtype, pkgbase)
|
self._text = cur.fetchone()[0]
|
||||||
body += '\n\n' + text
|
self._reqid = int(reqid)
|
||||||
refs = '[1] ' + user_uri + '\n'
|
self._reqtype = reqtype
|
||||||
refs += '[2] ' + pkgbase_uri
|
self._merge_into = merge_into
|
||||||
thread_id = '<pkg-request-' + reqid + '@aur.archlinux.org>'
|
|
||||||
# Use a deterministic Message-ID for the first email referencing a request.
|
def get_recipients(self):
|
||||||
headers = headers_msgid(thread_id)
|
return [self._to]
|
||||||
headers.update(headers_cc(cc))
|
|
||||||
|
def get_subject(self):
|
||||||
send_notification(to, subject, body, refs, headers)
|
return '[PRQ#%d] %s Request for %s' % \
|
||||||
|
(self._reqid, self._reqtype.title(), self._pkgbase)
|
||||||
|
|
||||||
def request_close(conn, uid, reqid, reason):
|
def get_body(self):
|
||||||
to = [aur_request_ml]
|
if self._merge_into:
|
||||||
cc = get_request_recipients(conn, reqid)
|
body = '%s [1] filed a request to merge %s [2] into %s [3]:' % \
|
||||||
text = get_request_closure_comment(conn, reqid)
|
(self._user, self._pkgbase, self._merge_into)
|
||||||
|
body += '\n\n' + self._text
|
||||||
subject = '[PRQ#%d] Request %s' % (int(reqid), reason.title())
|
else:
|
||||||
if int(uid):
|
body = '%s [1] filed a %s request for %s [2]:' % \
|
||||||
user = username_from_id(conn, uid)
|
(self._user, self._reqtype, self._pkgbase)
|
||||||
user_uri = aur_location + '/account/' + user + '/'
|
body += '\n\n' + self._text
|
||||||
body = 'Request #%d has been %s by %s [1]' % (int(reqid), reason, user)
|
return body
|
||||||
refs = '[1] ' + user_uri
|
|
||||||
else:
|
def get_refs(self):
|
||||||
body = 'Request #%d has been %s automatically by the Arch User ' \
|
refs = (aur_location + '/account/' + self._user + '/',
|
||||||
'Repository package request system' % (int(reqid), reason)
|
aur_location + '/pkgbase/' + self._pkgbase + '/')
|
||||||
refs = None
|
if self._merge_into:
|
||||||
if text.strip() == '':
|
refs += (aur_location + '/pkgbase/' + self._merge_into + '/',)
|
||||||
body += '.'
|
return refs
|
||||||
else:
|
|
||||||
body += ':\n\n' + text
|
def get_headers(self):
|
||||||
thread_id = '<pkg-request-' + reqid + '@aur.archlinux.org>'
|
thread_id = '<pkg-request-' + str(self._reqid) + '@aur.archlinux.org>'
|
||||||
headers = headers_reply(thread_id)
|
# Use a deterministic Message-ID for the first email referencing a
|
||||||
headers.update(headers_cc(cc))
|
# request.
|
||||||
|
headers = headers_msgid(thread_id)
|
||||||
send_notification(to, subject, body, refs, headers)
|
headers.update(headers_cc(self._cc))
|
||||||
|
return headers
|
||||||
|
|
||||||
def tu_vote_reminder(conn, vote_id):
|
|
||||||
to = get_tu_vote_reminder_recipients(conn, vote_id)
|
class RequestCloseNotification(Notification):
|
||||||
|
def __init__(self, conn, uid, reqid, reason):
|
||||||
vote_uri = aur_location + '/tu/?id=' + vote_id
|
self._user = username_from_id(conn, uid) if int(uid) else None
|
||||||
|
cur = conn.execute('SELECT DISTINCT Users.Email FROM PackageRequests ' +
|
||||||
subject = 'TU Vote Reminder: Proposal %d' % (int(vote_id))
|
'INNER JOIN PackageBases ' +
|
||||||
body = 'Please remember to cast your vote on proposal %d [1]. ' \
|
'ON PackageBases.ID = PackageRequests.PackageBaseID ' +
|
||||||
'The voting period ends in less than 48 hours.' % (int(vote_id))
|
'INNER JOIN Users ' +
|
||||||
refs = '[1] ' + vote_uri
|
'ON Users.ID = PackageRequests.UsersID ' +
|
||||||
|
'OR Users.ID = PackageBases.MaintainerUID ' +
|
||||||
send_notification(to, subject, body, refs)
|
'WHERE PackageRequests.ID = ?', [reqid])
|
||||||
|
self._to = aurweb.config.get('options', 'aur_request_ml')
|
||||||
|
self._cc = [row[0] for row in cur.fetchall()]
|
||||||
|
cur = conn.execute('SELECT ClosureComment FROM PackageRequests ' +
|
||||||
|
'WHERE ID = ?', [reqid])
|
||||||
|
self._text = cur.fetchone()[0]
|
||||||
|
self._reqid = int(reqid)
|
||||||
|
self._reason = reason
|
||||||
|
|
||||||
|
def get_recipients(self):
|
||||||
|
return [self._to]
|
||||||
|
|
||||||
|
def get_subject(self):
|
||||||
|
return '[PRQ#%d] Request %s' % (self._reqid, self._reason.title())
|
||||||
|
|
||||||
|
def get_body(self):
|
||||||
|
if self._user:
|
||||||
|
body = 'Request #%d has been %s by %s [1]' % \
|
||||||
|
(self._reqid, self._reason, self._user)
|
||||||
|
else:
|
||||||
|
body = 'Request #%d has been %s automatically by the Arch User ' \
|
||||||
|
'Repository package request system' % \
|
||||||
|
(self._reqid, self._reason)
|
||||||
|
if self._text.strip() == '':
|
||||||
|
body += '.'
|
||||||
|
else:
|
||||||
|
body += ':\n\n' + self._text
|
||||||
|
return body
|
||||||
|
|
||||||
|
def get_refs(self):
|
||||||
|
if self._user:
|
||||||
|
return (aur_location + '/account/' + self._user + '/',)
|
||||||
|
else:
|
||||||
|
return ()
|
||||||
|
|
||||||
|
def get_headers(self):
|
||||||
|
thread_id = '<pkg-request-' + str(self._reqid) + '@aur.archlinux.org>'
|
||||||
|
headers = headers_reply(thread_id)
|
||||||
|
headers.update(headers_cc(self._cc))
|
||||||
|
return headers
|
||||||
|
|
||||||
|
|
||||||
|
class TUVoteReminderNotification(Notification):
|
||||||
|
def __init__(self, conn, vote_id):
|
||||||
|
self._vote_id = int(vote_id)
|
||||||
|
cur = conn.execute('SELECT Email FROM Users ' +
|
||||||
|
'WHERE AccountTypeID IN (2, 4) AND ID NOT IN ' +
|
||||||
|
'(SELECT UserID FROM TU_Votes ' +
|
||||||
|
'WHERE TU_Votes.VoteID = ?)', [vote_id])
|
||||||
|
self._to = [row[0] for row in cur.fetchall()]
|
||||||
|
|
||||||
|
def get_recipients(self):
|
||||||
|
return self._to
|
||||||
|
|
||||||
|
def get_subject(self):
|
||||||
|
return 'TU Vote Reminder: Proposal %d' % (self._vote_id)
|
||||||
|
|
||||||
|
def get_body(self):
|
||||||
|
return 'Please remember to cast your vote on proposal %d [1]. ' \
|
||||||
|
'The voting period ends in less than 48 hours.' % \
|
||||||
|
(self._vote_id)
|
||||||
|
|
||||||
|
def get_refs(self):
|
||||||
|
return (aur_location + '/tu/?id=' + str(self._vote_id),)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
action = sys.argv[1]
|
action = sys.argv[1]
|
||||||
action_map = {
|
action_map = {
|
||||||
'send-resetkey': send_resetkey,
|
'send-resetkey': ResetKeyNotification,
|
||||||
'welcome': welcome,
|
'welcome': WelcomeNotification,
|
||||||
'comment': comment,
|
'comment': CommentNotification,
|
||||||
'update': update,
|
'update': UpdateNotification,
|
||||||
'flag': flag,
|
'flag': FlagNotification,
|
||||||
'adopt': adopt,
|
'adopt': AdoptNotification,
|
||||||
'disown': disown,
|
'disown': DisownNotification,
|
||||||
'comaintainer-add': comaintainer_add,
|
'comaintainer-add': ComaintainerAddNotification,
|
||||||
'comaintainer-remove': comaintainer_remove,
|
'comaintainer-remove': ComaintainerRemoveNotification,
|
||||||
'delete': delete,
|
'delete': DeleteNotification,
|
||||||
'request-open': request_open,
|
'request-open': RequestOpenNotification,
|
||||||
'request-close': request_close,
|
'request-close': RequestCloseNotification,
|
||||||
'tu-vote-reminder': tu_vote_reminder,
|
'tu-vote-reminder': TUVoteReminderNotification,
|
||||||
}
|
}
|
||||||
|
|
||||||
conn = aurweb.db.Connection()
|
conn = aurweb.db.Connection()
|
||||||
|
|
||||||
action_map[action](conn, *sys.argv[2:])
|
notification = action_map[action](conn, *sys.argv[2:])
|
||||||
|
notification.send()
|
||||||
|
|
||||||
conn.commit()
|
conn.commit()
|
||||||
conn.close()
|
conn.close()
|
||||||
|
|
Loading…
Add table
Reference in a new issue