diff options
author | Evgeny Fadeev <evgeny.fadeev@gmail.com> | 2010-05-24 20:51:30 -0400 |
---|---|---|
committer | Evgeny Fadeev <evgeny.fadeev@gmail.com> | 2010-05-24 20:51:30 -0400 |
commit | e673f4a6b977816fb2b9048083e7549d3de7227c (patch) | |
tree | de941442a4742a7bb3bee30f32bc9b7d27e5e27b | |
parent | 1881f765d56d842b4a0d31e2432e577fa01a6447 (diff) | |
download | askbot-e673f4a6b977816fb2b9048083e7549d3de7227c.tar.gz askbot-e673f4a6b977816fb2b9048083e7549d3de7227c.tar.bz2 askbot-e673f4a6b977816fb2b9048083e7549d3de7227c.zip |
instant notification on comment works
-rw-r--r-- | forum/const/__init__.py | 8 | ||||
-rw-r--r-- | forum/management/commands/send_email_alerts.py | 4 | ||||
-rw-r--r-- | forum/models/__init__.py | 210 | ||||
-rw-r--r-- | forum/models/base.py | 15 | ||||
-rw-r--r-- | forum/models/meta.py | 11 | ||||
-rw-r--r-- | forum/models/signals.py | 4 | ||||
-rw-r--r-- | forum/models/user.py | 21 | ||||
-rw-r--r-- | forum/models/utils.py (renamed from forum/utils/markup.py) | 0 | ||||
-rw-r--r-- | forum/skins/default/templates/instant_notification.html | 53 |
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 %} |