|
a/Allura/allura/model/notification.py |
|
b/Allura/allura/model/notification.py |
|
... |
|
... |
42 |
MAILBOX_QUIESCENT=None # Re-enable with [#1384]: timedelta(minutes=10)
|
42 |
MAILBOX_QUIESCENT=None # Re-enable with [#1384]: timedelta(minutes=10)
|
43 |
|
43 |
|
44 |
class Notification(MappedClass):
|
44 |
class Notification(MappedClass):
|
45 |
'''
|
45 |
'''
|
46 |
Temporarily store notifications that will be emailed or displayed as a web flash.
|
46 |
Temporarily store notifications that will be emailed or displayed as a web flash.
|
|
|
47 |
This does not contain any recipient information.
|
47 |
'''
|
48 |
'''
|
48 |
|
49 |
|
49 |
class __mongometa__:
|
50 |
class __mongometa__:
|
50 |
session = main_orm_session
|
51 |
session = main_orm_session
|
51 |
name = 'notification'
|
52 |
name = 'notification'
|
|
... |
|
... |
104 |
mbox.queue.append(n._id)
|
105 |
mbox.queue.append(n._id)
|
105 |
return n
|
106 |
return n
|
106 |
|
107 |
|
107 |
@classmethod
|
108 |
@classmethod
|
108 |
def _make_notification(cls, artifact, topic, **kwargs):
|
109 |
def _make_notification(cls, artifact, topic, **kwargs):
|
|
|
110 |
'''
|
|
|
111 |
Create a Notification instance based on an artifact. Special handling
|
|
|
112 |
for comments when topic=='message'
|
|
|
113 |
'''
|
|
|
114 |
|
109 |
from allura.model import Project
|
115 |
from allura.model import Project
|
110 |
idx = artifact.index()
|
116 |
idx = artifact.index()
|
111 |
subject_prefix = '[%s:%s] ' % (
|
117 |
subject_prefix = '[%s:%s] ' % (
|
112 |
c.project.shortname, c.app.config.options.mount_point)
|
118 |
c.project.shortname, c.app.config.options.mount_point)
|
113 |
if topic == 'message':
|
119 |
if topic == 'message':
|
|
... |
|
... |
265 |
reply_to=from_address,
|
271 |
reply_to=from_address,
|
266 |
subject=subject,
|
272 |
subject=subject,
|
267 |
message_id=h.gen_message_id(),
|
273 |
message_id=h.gen_message_id(),
|
268 |
text=text)
|
274 |
text=text)
|
269 |
|
275 |
|
|
|
276 |
|
270 |
class Mailbox(MappedClass):
|
277 |
class Mailbox(MappedClass):
|
|
|
278 |
'''
|
|
|
279 |
Holds a queue of notifications for an artifact, or a user (webflash messages)
|
|
|
280 |
for a subscriber.
|
|
|
281 |
FIXME: describe the Mailbox concept better.
|
|
|
282 |
'''
|
|
|
283 |
|
271 |
class __mongometa__:
|
284 |
class __mongometa__:
|
272 |
session = main_orm_session
|
285 |
session = main_orm_session
|
273 |
name = 'mailbox'
|
286 |
name = 'mailbox'
|
274 |
unique_indexes = [
|
287 |
unique_indexes = [
|
275 |
('user_id', 'project_id', 'app_config_id',
|
288 |
('user_id', 'project_id', 'app_config_id',
|
|
... |
|
... |
295 |
is_flash = FieldProperty(bool, if_missing=False)
|
308 |
is_flash = FieldProperty(bool, if_missing=False)
|
296 |
type = FieldProperty(S.OneOf('direct', 'digest', 'summary', 'flash'))
|
309 |
type = FieldProperty(S.OneOf('direct', 'digest', 'summary', 'flash'))
|
297 |
frequency = FieldProperty(dict(
|
310 |
frequency = FieldProperty(dict(
|
298 |
n=int,unit=S.OneOf('day', 'week', 'month')))
|
311 |
n=int,unit=S.OneOf('day', 'week', 'month')))
|
299 |
next_scheduled = FieldProperty(datetime, if_missing=datetime.utcnow)
|
312 |
next_scheduled = FieldProperty(datetime, if_missing=datetime.utcnow)
|
300 |
|
|
|
301 |
# Actual notification IDs
|
|
|
302 |
last_modified = FieldProperty(datetime, if_missing=datetime(2000,1,1))
|
313 |
last_modified = FieldProperty(datetime, if_missing=datetime(2000,1,1))
|
|
|
314 |
|
|
|
315 |
# a list of notification _id values
|
303 |
queue = FieldProperty([str])
|
316 |
queue = FieldProperty([str])
|
304 |
|
317 |
|
305 |
project = RelationProperty('Project')
|
318 |
project = RelationProperty('Project')
|
306 |
app_config = RelationProperty('AppConfig')
|
319 |
app_config = RelationProperty('AppConfig')
|
307 |
|
320 |
|
|
... |
|
... |
396 |
artifact_index_id=artifact_index_id)).count() != 0
|
409 |
artifact_index_id=artifact_index_id)).count() != 0
|
397 |
|
410 |
|
398 |
@classmethod
|
411 |
@classmethod
|
399 |
def deliver(cls, nid, artifact_index_id, topic):
|
412 |
def deliver(cls, nid, artifact_index_id, topic):
|
400 |
'''Called in the notification message handler to deliver notification IDs
|
413 |
'''Called in the notification message handler to deliver notification IDs
|
401 |
to the appropriate mailboxes. Atomically appends the nids
|
414 |
to the appropriate mailboxes. Atomically appends the nids
|
402 |
to the appropriate mailboxes.
|
415 |
to the appropriate mailboxes.
|
403 |
'''
|
416 |
'''
|
404 |
d = {
|
417 |
d = {
|
405 |
'project_id':c.project._id,
|
418 |
'project_id':c.project._id,
|
406 |
'app_config_id':c.app.config._id,
|
419 |
'app_config_id':c.app.config._id,
|
|
... |
|
... |
415 |
session(mbox).expunge(mbox)
|
428 |
session(mbox).expunge(mbox)
|
416 |
|
429 |
|
417 |
@classmethod
|
430 |
@classmethod
|
418 |
def fire_ready(cls):
|
431 |
def fire_ready(cls):
|
419 |
'''Fires all direct subscriptions with notifications as well as
|
432 |
'''Fires all direct subscriptions with notifications as well as
|
420 |
all summary & digest subscriptions with notifications that are ready
|
433 |
all summary & digest subscriptions with notifications that are ready.
|
|
|
434 |
Clears the mailbox queue.
|
421 |
'''
|
435 |
'''
|
422 |
now = datetime.utcnow()
|
436 |
now = datetime.utcnow()
|
423 |
# Queries to find all matching subscription objects
|
437 |
# Queries to find all matching subscription objects
|
424 |
q_direct = dict(
|
438 |
q_direct = dict(
|
425 |
type='direct',
|
439 |
type='direct',
|
|
... |
|
... |
451 |
queue=[])},
|
465 |
queue=[])},
|
452 |
new=False)
|
466 |
new=False)
|
453 |
mbox.fire(now)
|
467 |
mbox.fire(now)
|
454 |
|
468 |
|
455 |
def fire(self, now):
|
469 |
def fire(self, now):
|
|
|
470 |
'''
|
|
|
471 |
Send all notifications that this mailbox has enqueued.
|
|
|
472 |
'''
|
456 |
notifications = Notification.query.find(dict(_id={'$in':self.queue}))
|
473 |
notifications = Notification.query.find(dict(_id={'$in':self.queue}))
|
457 |
notifications = notifications.all()
|
474 |
notifications = notifications.all()
|
458 |
if self.type == 'direct':
|
475 |
if self.type == 'direct':
|
459 |
ngroups = defaultdict(list)
|
476 |
ngroups = defaultdict(list)
|
460 |
for n in notifications:
|
477 |
for n in notifications:
|
|
... |
|
... |
478 |
notifications)
|
495 |
notifications)
|
479 |
elif self.type == 'summary':
|
496 |
elif self.type == 'summary':
|
480 |
Notification.send_summary(
|
497 |
Notification.send_summary(
|
481 |
self.user_id, u'noreply@in.sf.net', 'Digest Email',
|
498 |
self.user_id, u'noreply@in.sf.net', 'Digest Email',
|
482 |
notifications)
|
499 |
notifications)
|
483 |
# remove Notifications since they are no longer needed
|
|
|
484 |
Notification.query.remove({'_id': {'$in': [n._id for n in notifications]}})
|
|
|