summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEvgeny Fadeev <evgeny.fadeev@gmail.com>2010-05-24 20:51:30 -0400
committerEvgeny Fadeev <evgeny.fadeev@gmail.com>2010-05-24 20:51:30 -0400
commite673f4a6b977816fb2b9048083e7549d3de7227c (patch)
treede941442a4742a7bb3bee30f32bc9b7d27e5e27b
parent1881f765d56d842b4a0d31e2432e577fa01a6447 (diff)
downloadaskbot-e673f4a6b977816fb2b9048083e7549d3de7227c.tar.gz
askbot-e673f4a6b977816fb2b9048083e7549d3de7227c.tar.bz2
askbot-e673f4a6b977816fb2b9048083e7549d3de7227c.zip
instant notification on comment works
-rw-r--r--forum/const/__init__.py8
-rw-r--r--forum/management/commands/send_email_alerts.py4
-rw-r--r--forum/models/__init__.py210
-rw-r--r--forum/models/base.py15
-rw-r--r--forum/models/meta.py11
-rw-r--r--forum/models/signals.py4
-rw-r--r--forum/models/user.py21
-rw-r--r--forum/models/utils.py (renamed from forum/utils/markup.py)0
-rw-r--r--forum/skins/default/templates/instant_notification.html53
9 files changed, 192 insertions, 134 deletions
diff --git a/forum/const/__init__.py b/forum/const/__init__.py
index dba43161..e7328c54 100644
--- a/forum/const/__init__.py
+++ b/forum/const/__init__.py
@@ -137,14 +137,6 @@ RESPONSE_ACTIVITY_TYPES_FOR_DISPLAY = (
TYPE_ACTIVITY_FAVORITE,
)
-RESPONSE_ACTIVITY_TYPES_FOR_EMAIL = (
- TYPE_ACTIVITY_COMMENT_QUESTION,
- TYPE_ACTIVITY_COMMENT_ANSWER,
- TYPE_ACTIVITY_UPDATE_ANSWER,
- TYPE_ACTIVITY_UPDATE_QUESTION,
- TYPE_ACTIVITY_MENTION,
-)
-
TYPE_RESPONSE = {
'QUESTION_ANSWERED' : _('question_answered'),
'QUESTION_COMMENTED': _('question_commented'),
diff --git a/forum/management/commands/send_email_alerts.py b/forum/management/commands/send_email_alerts.py
index 75a2e7cb..ccda1081 100644
--- a/forum/management/commands/send_email_alerts.py
+++ b/forum/management/commands/send_email_alerts.py
@@ -451,8 +451,8 @@ class Command(NoArgsCommand):
# text += '</p>'
link = url_prefix + user.get_profile_url() + '?sort=email_subscriptions'
- text += _('go to %(link)s to change frequency of email updates or %(email)s administrator') \
- % {'link':link, 'email':settings.ADMINS[0][1]}
+ text += _('go to %(email_settings_link)s to change frequency of email updates or %(admin_email)s administrator') \
+ % {'email_settings_link':link, 'admin_email':settings.ADMINS[0][1]}
if DEBUG_THIS_COMMAND == False:
msg = EmailMessage(subject, text, settings.DEFAULT_FROM_EMAIL, [user.email])
msg.content_subtype = 'html'
diff --git a/forum/models/__init__.py b/forum/models/__init__.py
index ebcbe6e2..d907b27f 100644
--- a/forum/models/__init__.py
+++ b/forum/models/__init__.py
@@ -246,6 +246,64 @@ User.add_to_class(
user_should_receive_instant_notification_about_post
)
+
+def send_instant_notifications_about_activity_in_post(
+ activity,
+ post,
+ receiving_users
+ ):
+ """
+ function called when posts are updated
+ """
+
+ #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',
+ }
+
+ template = loader.get_template('instant_notification.html')
+ for u in receiving_users:
+ 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)
+
+ #get details about update
+ #todo: is there a way to solve this import issue?
+ from forum.conf import settings as forum_settings
+ base_url = forum_settings.APP_URL
+ data = {
+ 'receiving_user': u,
+ 'update_author': activity.user,
+ 'updated_post': post,
+ 'update_url': base_url + post.get_absolute_url(),
+ 'update_type': update_type_map[activity.activity_type],
+ 'revision_number': post.get_latest_revision_number(),
+ 'related_origin_post': post.get_origin_post(),
+ 'admin_email': settings.ADMINS[0][1],
+ #todo: clean up url calculation below
+ 'email_settings_url': base_url + u.get_profile_url() \
+ + '?sort=email_subscriptions'
+ }
+ #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 calculate_gravatar_hash(instance, **kwargs):
"""Calculates a User's gravatar hash from their email address."""
if kwargs.get('raw', False):
@@ -300,37 +358,54 @@ def record_answer_event(instance, created, **kwargs):
activity.receiving_users.add(*receiving_users)
-def record_comment_event(instance, created, **kwargs):
- if created:
- if isinstance(instance.content_object, Question):
- activity_type = const.TYPE_ACTIVITY_COMMENT_QUESTION
- 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)
+def record_comment_event(instance, **kwargs):
+ if isinstance(instance.content_object, Question):
+ activity_type = const.TYPE_ACTIVITY_COMMENT_QUESTION
+ 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)
+ )
+
+ activity = Activity(
+ user = instance.user,
+ active_at = instance.added_at,
+ content_object = instance,
+ activity_type = activity_type
+ )
+ activity.save()
+
+ receiving_users = set()
+ receiving_users.update(
+ #get authors of parent object and all associated comments
+ instance.content_object.get_author_list(
+ include_comments = True,
+ )
)
- activity = Activity(
- user = instance.user,
- active_at = instance.added_at,
- content_object = instance,
- activity_type = activity_type
+ receiving_users.update(
+ instance.get_newly_mentioned_users()
)
- activity.save()
- receiving_users = instance.content_object.get_author_list(
- include_comments = True,
- 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)
+ receiving_users -= set([instance.user])#remove activity user
+ receiving_users = list(receiving_users)
+
+ activity.receiving_users.add(*receiving_users)
+
+ print 'in post_save handler on comment'
+ print receiving_users
+
+ send_instant_notifications_about_activity_in_post(
+ activity,
+ instance,
+ receiving_users
+ )
def record_revision_question_event(instance, created, **kwargs):
- if created and instance.revision <> 1:
+ if created and instance.revision != 1:
activity = Activity(
user=instance.author,
active_at=instance.revised_at,
@@ -342,16 +417,30 @@ def record_revision_question_event(instance, created, **kwargs):
receiving_users.update(
instance.question.get_author_list(include_comments = True)
)
+
+ receiving_users.update(
+ )
for a in instance.question.answers:
receiving_users.update(a.get_author_list())
- receiving_users -= set([instance.author])
+
+ receiving_users.update(
+ instance.question.get_newly_mentioned_users()
+ )
+
+ receiving_users -= set([instance.author])#remove activity user
receiving_users = list(receiving_users)
activity.receiving_users.add(*receiving_users)
+ send_instant_notifications_about_activity_in_post(
+ activity,
+ instance.question,
+ receiving_users
+ )
+
def record_revision_answer_event(instance, created, **kwargs):
- if created and instance.revision <> 1:
+ if created and instance.revision != 1:
activity = Activity(
user=instance.author,
active_at=instance.revised_at,
@@ -366,69 +455,21 @@ def record_revision_answer_event(instance, created, **kwargs):
)
)
receiving_users.update(instance.answer.question.get_author_list())
+
+ receiving_users.update(
+ instance.answer.get_newly_mentioned_users()
+ )
+
receiving_users -= set([instance.author])
receiving_users = list(receiving_users)
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
+ send_instant_notifications_about_activity_in_post(
+ activity,
+ instance.answer,
+ receiving_users
)
- 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):
"""
@@ -618,7 +659,6 @@ def post_stored_anonymous_content(sender,user,session_key,signal,*args,**kwargs)
pre_save.connect(calculate_gravatar_hash, sender=User)
post_save.connect(record_ask_event, sender=Question)
post_save.connect(record_answer_event, sender=Answer)
-post_save.connect(record_comment_event, sender=Comment)
post_save.connect(record_revision_question_event, sender=QuestionRevision)
post_save.connect(record_revision_answer_event, sender=AnswerRevision)
post_save.connect(record_award_event, sender=Award)
@@ -630,7 +670,6 @@ post_save.connect(record_favorite_question, sender=FavoriteQuestion)
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)
@@ -638,6 +677,7 @@ 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)
+signals.comment_post_save.connect(record_comment_event, sender=Comment)
#post_syncdb.connect(create_fulltext_indexes)
#todo: wtf??? what is x=x about?
diff --git a/forum/models/base.py b/forum/models/base.py
index 068effbd..c153bb5d 100644
--- a/forum/models/base.py
+++ b/forum/models/base.py
@@ -21,6 +21,19 @@ import logging
from forum.const import *
+#todo: this method belongs to a common post class
+def get_newly_mentioned_users_in_post(post):
+ from forum.models import Activity
+ mentions = Activity.objects.get_mentions(
+ mentioned_in = post,
+ reported = False
+ )
+ users = set()
+ for m in mentions:
+ users.update(m.receiving_users.all())
+ return list(users)
+
+
class UserContent(models.Model):
user = models.ForeignKey(User, related_name='%(class)ss')
@@ -171,6 +184,8 @@ class Content(models.Model):
authors -= set(exclude_list)
return list(authors)
+ get_newly_mentioned_users = get_newly_mentioned_users_in_post
+
def passes_tag_filter_for_user(self, user):
tags = self.get_origin_post().tags.all()
diff --git a/forum/models/meta.py b/forum/models/meta.py
index 8382fec7..0e49064e 100644
--- a/forum/models/meta.py
+++ b/forum/models/meta.py
@@ -1,6 +1,7 @@
from base import *
from forum import const
from django.utils.html import urlize
+from forum.models import signals
class VoteManager(models.Manager):
def get_up_vote_count_from_user(self, user):
@@ -88,11 +89,17 @@ class Comment(MetaContent, UserContent):
return self.content_object.get_origin_post()
def save(self,**kwargs):
- from forum.utils.markup import mentionize
+ print 'before first save'
super(Comment,self).save(**kwargs)
+ print 'after first save'
+ from forum.models.utils import mentionize
self.html = mentionize(urlize(self.comment, nofollow=True), context_object = self)
+ print 'mentionized'
#todo - try post_save to install mentions
super(Comment,self).save(**kwargs)#have to save twice!!, b/c need id for generic relation
+
+ signals.comment_post_save.send(instance = self, sender = Comment)
+
try:
ping_google()
except Exception:
@@ -114,5 +121,7 @@ class Comment(MetaContent, UserContent):
def get_latest_revision_number(self):
return 1
+ get_newly_mentioned_users = get_newly_mentioned_users_in_post
+
def __unicode__(self):
return self.comment
diff --git a/forum/models/signals.py b/forum/models/signals.py
index b32ffe4a..b3850979 100644
--- a/forum/models/signals.py
+++ b/forum/models/signals.py
@@ -13,5 +13,5 @@ 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'])
+
+comment_post_save = django.dispatch.Signal(providing_args=['instance'])
diff --git a/forum/models/user.py b/forum/models/user.py
index ef709c70..d7678801 100644
--- a/forum/models/user.py
+++ b/forum/models/user.py
@@ -76,12 +76,6 @@ 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
@@ -146,21 +140,6 @@ class Activity(models.Model):
def __unicode__(self):
return u'[%s] was active at %s' % (self.user.username, self.active_at)
- def get_response_type_content_object(self):
- """
- This method will go when post models are
- unified (todo:)
- """
- cobj = self.content_object
- if isinstance(cobj, Comment):
- return cobj
- elif isinstance(cobj, AnswerRevision):
- return cobj.answer
- elif isinstance(cobj, QuestionRevision):
- return cobj.question
- else:
- raise NotImplementedError()
-
class Meta:
app_label = 'forum'
db_table = u'activity'
diff --git a/forum/utils/markup.py b/forum/models/utils.py
index bfe7b1c9..bfe7b1c9 100644
--- a/forum/utils/markup.py
+++ b/forum/models/utils.py
diff --git a/forum/skins/default/templates/instant_notification.html b/forum/skins/default/templates/instant_notification.html
index 1bab99cf..3f4da467 100644
--- a/forum/skins/default/templates/instant_notification.html
+++ b/forum/skins/default/templates/instant_notification.html
@@ -9,24 +9,47 @@ related_origin_post - origin post related to the update
update_url - absolute url (including http://... to updated post
update_type - question_comment|answer_comment|answer_update|question_update
revision_number - integer (first revision is 1)
-has_mention - Boolean
+admin_email - email of forum administrator
+email_settings_url - url of user's email settings
{% endcomment %}
{% load i18n %}
{% load smart_if %}
{% blocktrans with receiving_user.get_best_name as user_name %}Dear {{user_name}},{% endblocktrans %}
-{% if has_mention %}
- {% if update_type == 'question_comment' or update_type == 'answer_comment' %}
- {% blocktrans with post_author.get_profile_link as author_link and related_origin_post.get_absolute_url as origin_post_url and related_origin_post.title as origin_post_title %}
- {{author_link}} has left you a <a href="{{update_url}}">comment</a>
- related to question <a href="{{origin_post_url}}">{{origin_post_title}}</a>
- {% endblocktrans %}
- {% endif %}
-{% else %}{# updated post has no mention of user #}
- {% if update_type == 'question_comment' or update_type == 'answer_comment' %}
- {% blocktrans with post_author.get_profile_link as author_link and related_origin_post.get_absolute_url as origin_post_url and related_origin_post.title as origin_post_title %}
- {{author_link}} has left a new <a href="{{update_url}}">comment</a>
- related to question <a href="{{origin_post_url}}">{{origin_post_title}}</a>
- {% endblocktrans %}
- {% endif %}
+{% if update_type == 'question_comment' or update_type == 'answer_comment' %}
+{% blocktrans with post_author.get_profile_link as author_link and related_origin_post.get_absolute_url as origin_post_url and related_origin_post.title as origin_post_title %}
+{{author_link}} has left a new <a href="{{update_url}}">comment</a>
+related to question <a href="{{origin_post_url}}">{{origin_post_title}}</a>
+{% endblocktrans %}
{% endif %}
+{% if update_type == 'answer_update' %}
+{% if revision_number == 1 %}
+{% blocktrans with post_author.get_profile_link as author_link and related_origin_post.get_absolute_url as origin_post_url and related_origin_post.title as origin_post_title %}
+{{author_link}} posted <a href="{{update_url}}">a new answer</a>
+to question <a href="{{origin_post_url}}">{{origin_post_title}}</a>
+{% endblocktrans %}
+{% else %}
+{% blocktrans with post_author.get_profile_link as author_link and related_origin_post.get_absolute_url as origin_post_url and related_origin_post.title as origin_post_title %}
+{{author_link}} updated <a href="{{update_url}}">an answer</a>
+to question <a href="{{origin_post_url}}">{{origin_post_title}}</a>
+{% endblocktrans %}
+{% endif %}
+{% endif %}
+{% if update_type == 'question_update' %}
+{% if revision_number == 1 %}
+{% blocktrans with post_author.get_profile_link as author_link and related_origin_post.get_absolute_url as origin_post_url and related_origin_post.title as origin_post_title %}
+{{author_link}} asked a new question <a href="{{origin_post_url}}">{{origin_post_title}}</a>
+{% endblocktrans %}
+{% else %}
+{% blocktrans with post_author.get_profile_link as author_link and related_origin_post.get_absolute_url as origin_post_url and related_origin_post.title as origin_post_title %}
+{{author_link}} updated the question <a href="{{origin_post_url}}">{{origin_post_title}}</a>
+{% endblocktrans %}
+{% endif %}
+{% endif %}
+
+{% trans "Please take a look." %}
+
+{% blocktrans %}Sincerely,
+Forum Administrator{% endblocktrans %}
+
+{% blocktrans %}go to {{email_settings_url}} to change frequency of email updates or {{admin_email}} administrator{% endblocktrans %}