summaryrefslogtreecommitdiffstats
path: root/forum/models
diff options
context:
space:
mode:
Diffstat (limited to 'forum/models')
-rw-r--r--forum/models/__init__.py118
-rw-r--r--forum/models/question.py5
-rw-r--r--forum/models/signals.py17
-rw-r--r--forum/models/user.py8
4 files changed, 127 insertions, 21 deletions
diff --git a/forum/models/__init__.py b/forum/models/__init__.py
index 1c20e74b..ebcbe6e2 100644
--- a/forum/models/__init__.py
+++ b/forum/models/__init__.py
@@ -5,9 +5,13 @@ from meta import Vote, Comment, FlaggedItem
from user import Activity, ValidationHash, EmailFeedSetting
from user import AuthKeyUserAssociation
from repute import Badge, Award, Repute
+import signals
from django.core.urlresolvers import reverse
+from django.core.mail import EmailMessage
from forum.search.indexer import create_fulltext_indexes
from django.db.models.signals import post_syncdb
+from django.template import loader, Context
+from django.utils.translation import ugettext as _
from forum import const
import logging
import re
@@ -16,15 +20,6 @@ from base import *
import datetime
from django.contrib.contenttypes.models import ContentType
-#todo: move to a separate file?
-# custom signals
-tags_updated = django.dispatch.Signal(providing_args=["question"])
-edit_question_or_answer = django.dispatch.Signal(providing_args=["instance", "modified_by"])
-delete_post_or_answer = django.dispatch.Signal(providing_args=["instance", "deleted_by"])
-mark_offensive = django.dispatch.Signal(providing_args=["instance", "mark_by"])
-user_updated = django.dispatch.Signal(providing_args=["instance", "updated_by"])
-user_logged_in = django.dispatch.Signal(providing_args=["session"])
-
#todo: must go after signals
from forum import auth
@@ -229,6 +224,14 @@ def flag_post(self, post, timestamp=None, cancel=False):
)
auth.onFlaggedItem(flag, post, user, timestamp=timestamp)
+def user_should_receive_instant_notification_about_post(user, post):
+ return EmailFeedSetting.objects.exists_match_to_post_and_subscriber(
+ subscriber = user,
+ post = post,
+ frequency = 'i',
+ )
+
+
User.add_to_class('upvote', upvote)
User.add_to_class('downvote', downvote)
User.add_to_class('accept_answer', accept_answer)
@@ -238,6 +241,10 @@ User.add_to_class('get_profile_link', get_profile_link)
User.add_to_class('get_messages', get_messages)
User.add_to_class('delete_messages', delete_messages)
User.add_to_class('toggle_favorite_question', toggle_favorite_question)
+User.add_to_class(
+ 'should_receive_instant_notification_about_post',
+ user_should_receive_instant_notification_about_post
+ )
def calculate_gravatar_hash(instance, **kwargs):
"""Calculates a User's gravatar hash from their email address."""
@@ -300,7 +307,10 @@ def record_comment_event(instance, created, **kwargs):
elif isinstance(instance.content_object, Answer):
activity_type = const.TYPE_ACTIVITY_COMMENT_ANSWER
else:
- logging.critical('recording comment for %s is not implemented' % type(instance.content_object))
+ logging.critical(
+ 'recording comment for %s is not implemented'\
+ % type(instance.content_object)
+ )
activity = Activity(
user = instance.user,
@@ -315,6 +325,8 @@ def record_comment_event(instance, created, **kwargs):
exclude_list = [instance.user],
)
activity.receiving_users.add(*receiving_users)
+ #todo: remove this upon migration to 1.2
+ signals.fake_m2m_changed.send(sender = Activity, instance = activity, created = True)
def record_revision_question_event(instance, created, **kwargs):
@@ -337,6 +349,7 @@ def record_revision_question_event(instance, created, **kwargs):
receiving_users = list(receiving_users)
activity.receiving_users.add(*receiving_users)
+
def record_revision_answer_event(instance, created, **kwargs):
if created and instance.revision <> 1:
activity = Activity(
@@ -358,6 +371,65 @@ def record_revision_answer_event(instance, created, **kwargs):
activity.receiving_users.add(*receiving_users)
+
+def maybe_send_instant_notifications(instance, created, **kwargs):
+ """todo: this handler must change when we switch to django 1.2
+ """
+ activity_instance = instance
+ if not created:
+ return
+ activity_type = activity_instance.activity_type
+ if activity_type not in const.RESPONSE_ACTIVITY_TYPES_FOR_EMAIL:
+ return
+
+ #todo: remove this after migrating to string type for const.TYPE_ACTIVITY...
+ update_type_map = {
+ const.TYPE_ACTIVITY_COMMENT_QUESTION: 'question_comment',
+ const.TYPE_ACTIVITY_COMMENT_ANSWER: 'answer_comment',
+ const.TYPE_ACTIVITY_UPDATE_ANSWER: 'answer_update',
+ const.TYPE_ACTIVITY_UPDATE_QUESTION: 'question_update',
+ const.TYPE_ACTIVITY_MENTION: 'mention',
+ }
+
+ post = activity_instance.get_response_type_content_object()
+ template = loader.get_template('instant_notification.html')
+ for u in activity_instance.receiving_users.all():
+ if u.should_receive_instant_notification_about_post(post):
+
+ mentions = Activity.objects.get_mentions(
+ mentioned_whom = u,
+ mentioned_in = post,
+ reported = False
+ )
+ if mentions:
+ #todo: find a more semantic way to do this
+ mentions.update(is_auditted = True)
+ has_mention = True
+ else:
+ has_mention = False
+
+ #get details about update
+ #todo: is there a way to solve this import issue?
+ from forum.conf import settings as forum_settings
+ data = {
+ 'receiving_user': u,
+ 'update_author': activity_instance.user,
+ 'updated_post': post,
+ 'update_url': forum_settings.APP_URL + post.get_absolute_url(),
+ 'update_type': update_type_map[activity_type],
+ 'revision_number': post.get_latest_revision_number(),
+ 'related_origin_post': post.get_origin_post(),
+ 'has_mention': has_mention,
+ }
+ #send update
+ subject = _('email update message subject')
+ text = template.render(Context(data))
+ msg = EmailMessage(subject, text, settings.DEFAULT_FROM_EMAIL, [u.email])
+ #print 'sending email to %s' % u.email
+ #print 'subject: %s' % subject
+ #print 'body: %s' % text
+ #msg.send()
+
def record_award_event(instance, created, **kwargs):
"""
After we awarded a badge to user, we need to record this activity and notify user.
@@ -542,7 +614,7 @@ def post_stored_anonymous_content(sender,user,session_key,signal,*args,**kwargs)
for aa in aa_list:
aa.publish(user)
-#signal for User modle save changes
+#signal for User model save changes
pre_save.connect(calculate_gravatar_hash, sender=User)
post_save.connect(record_ask_event, sender=Question)
post_save.connect(record_answer_event, sender=Answer)
@@ -554,17 +626,23 @@ post_save.connect(notify_award_message, sender=Award)
post_save.connect(record_answer_accepted, sender=Answer)
post_save.connect(update_last_seen, sender=Activity)
post_save.connect(record_vote, sender=Vote)
-post_delete.connect(record_cancel_vote, sender=Vote)
-delete_post_or_answer.connect(record_delete_question, sender=Question)
-delete_post_or_answer.connect(record_delete_question, sender=Answer)
-mark_offensive.connect(record_mark_offensive, sender=Question)
-mark_offensive.connect(record_mark_offensive, sender=Answer)
-tags_updated.connect(record_update_tags, sender=Question)
post_save.connect(record_favorite_question, sender=FavoriteQuestion)
-user_updated.connect(record_user_full_updated, sender=User)
-user_logged_in.connect(post_stored_anonymous_content)
+post_delete.connect(record_cancel_vote, sender=Vote)
+
+#change this to real m2m_changed with Django1.2
+signals.fake_m2m_changed.connect(maybe_send_instant_notifications, sender=Activity)
+signals.delete_post_or_answer.connect(record_delete_question, sender=Question)
+signals.delete_post_or_answer.connect(record_delete_question, sender=Answer)
+signals.mark_offensive.connect(record_mark_offensive, sender=Question)
+signals.mark_offensive.connect(record_mark_offensive, sender=Answer)
+signals.tags_updated.connect(record_update_tags, sender=Question)
+signals.user_updated.connect(record_user_full_updated, sender=User)
+signals.user_logged_in.connect(post_stored_anonymous_content)
#post_syncdb.connect(create_fulltext_indexes)
+#todo: wtf??? what is x=x about?
+signals = signals
+
Question = Question
QuestionRevision = QuestionRevision
QuestionView = QuestionView
@@ -591,6 +669,8 @@ ValidationHash = ValidationHash
AuthKeyUserAssociation = AuthKeyUserAssociation
__all__ = [
+ 'signals',
+
'Question',
'QuestionRevision',
'QuestionView',
diff --git a/forum/models/question.py b/forum/models/question.py
index c2fb6203..0793e601 100644
--- a/forum/models/question.py
+++ b/forum/models/question.py
@@ -1,4 +1,5 @@
from base import * #todo maybe remove *
+from forum.models import signals
from tag import Tag
#todo: make uniform import for consts
from forum.const import CONST
@@ -321,7 +322,7 @@ class Question(Content, DeletableContent):
self.last_activity_by = retagged_by
# Update the Question's tag associations
- tags_updated = self.objects.update_tags(
+ signals.tags_updated = self.objects.update_tags(
self,
form.cleaned_data['tags'],
request.user
@@ -339,7 +340,7 @@ class Question(Content, DeletableContent):
text = latest_revision.text
)
# send tags updated singal
- tags_updated.send(sender=question.__class__, question=self)
+ signals.tags_updated.send(sender=question.__class__, question=self)
def get_origin_post(self):
return self
diff --git a/forum/models/signals.py b/forum/models/signals.py
new file mode 100644
index 00000000..b32ffe4a
--- /dev/null
+++ b/forum/models/signals.py
@@ -0,0 +1,17 @@
+import django.dispatch
+
+tags_updated = django.dispatch.Signal(providing_args=['question'])
+
+#todo: this one seems to be unused
+edit_question_or_answer = django.dispatch.Signal(
+ providing_args=['instance', 'modified_by']
+ )
+delete_post_or_answer = django.dispatch.Signal(
+ providing_args=['instance', 'deleted_by']
+ )
+mark_offensive = django.dispatch.Signal(providing_args=['instance', 'mark_by'])
+user_updated = django.dispatch.Signal(providing_args=['instance', 'updated_by'])
+#todo: move this to authentication app
+user_logged_in = django.dispatch.Signal(providing_args=['session'])
+#todo: remove this upon migration to 1.2
+fake_m2m_changed = django.dispatch.Signal(providing_args=['instance','created'])
diff --git a/forum/models/user.py b/forum/models/user.py
index 2f4db6aa..ef709c70 100644
--- a/forum/models/user.py
+++ b/forum/models/user.py
@@ -1,5 +1,7 @@
from base import *
+#todo: remove this with Django 1.2
from django.contrib.contenttypes.models import ContentType
+from forum.models import signals
from django.contrib.contenttypes import generic
from django.contrib.auth.models import User
from forum.models.question import Question, QuestionRevision
@@ -74,6 +76,12 @@ class ActivityManager(models.Manager):
else:
mention_activity.receiving_users.add(mentioned_whom)
+ signals.fake_m2m_changed.send(
+ sender = Activity,
+ instance = mention_activity,
+ created = True
+ )
+
return mention_activity