From e19d24423069e0ee4f4b1fa2c0b079e57de83322 Mon Sep 17 00:00:00 2001 From: Evgeny Fadeev Date: Wed, 5 Aug 2009 22:55:06 -0400 Subject: added some more files --- forum/management/commands/send_email_alerts.py | 41 ++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 forum/management/commands/send_email_alerts.py (limited to 'forum/management/commands/send_email_alerts.py') diff --git a/forum/management/commands/send_email_alerts.py b/forum/management/commands/send_email_alerts.py new file mode 100644 index 00000000..3c37aaa3 --- /dev/null +++ b/forum/management/commands/send_email_alerts.py @@ -0,0 +1,41 @@ +from django.core.management.base import NoArgsCommand +from django.db import connection +from forum.models import * +import collections +from django.core.mail import EmailMessage +from django.utils.translation import ugettext as _ +import settings + +class Command(NoArgsCommand): + def handle_noargs(self,**options): + try: + self.send_email_alerts() + except Exception, e: + print e + finally: + connection.close() + + def send_email_alerts(self): + report_time = datetime.datetime.now() + feeds = EmailFeed.objects.all() + user_ctype = ContentType.objects.get_for_model(User) + + #lists of update messages keyed by email address + update_collection = collections.defaultdict(list) + for feed in feeds: + update_summary = feed.get_update_summary() + if update_summary != None: + email = feed.get_email() + update_collection[email].append(update_summary) + feed.reported_at = report_time + feed.save() + + for email, updates in update_collection.items(): + text = '\n'.join(updates) + subject = _('updates from website') + print 'sent %s to %s' % (updates,email) + msg = EmailMessage(subject, text, settings.DEFAULT_FROM_EMAIL, [email]) + msg.content_subtype = 'html' + msg.send() + + -- cgit v1.2.3-1-g7c22 From 40b5c06085fe3d079094e8ef779a7b119586f9e8 Mon Sep 17 00:00:00 2001 From: root Date: Fri, 13 Nov 2009 20:18:31 -0500 Subject: better comments, email subscriptions, corrected view counter, some ie7 issues, wiki optional with settings.WIKI_ON, site can be mounted on arbitrary url prefix, english language improvements, added feedback form, versioned css and js files to force browser cache reload when settings.RESOURCE_REVISION is incremented , other fixes --- forum/management/commands/send_email_alerts.py | 139 ++++++++++++++++++++----- 1 file changed, 115 insertions(+), 24 deletions(-) (limited to 'forum/management/commands/send_email_alerts.py') diff --git a/forum/management/commands/send_email_alerts.py b/forum/management/commands/send_email_alerts.py index 3c37aaa3..a25e4343 100644 --- a/forum/management/commands/send_email_alerts.py +++ b/forum/management/commands/send_email_alerts.py @@ -1,9 +1,11 @@ from django.core.management.base import NoArgsCommand from django.db import connection +from django.db.models import Q, F from forum.models import * -import collections from django.core.mail import EmailMessage from django.utils.translation import ugettext as _ +from django.utils.translation import ungettext +import datetime import settings class Command(NoArgsCommand): @@ -15,27 +17,116 @@ class Command(NoArgsCommand): finally: connection.close() + def get_updated_questions_for_user(self,user): + q_sel = [] + q_ask = [] + q_ans = [] + q_all = [] + now = datetime.datetime.now() + Q_set1 = Question.objects.exclude( + last_activity_by=user, + ).exclude( + last_activity_at__lt=user.date_joined + ).filter( + Q(viewed__who=user,viewed__when__lt=F('last_activity_at')) | \ + ~Q(viewed__who=user) + ).exclude( + deleted=True + ).exclude( + closed=True + ) + user_feeds = EmailFeedSetting.objects.filter(subscriber=user).exclude(frequency='n') + for feed in user_feeds: + cutoff_time = now - EmailFeedSetting.DELTA_TABLE[feed.frequency] + if feed.reported_at == None or feed.reported_at <= cutoff_time: + Q_set = Q_set1.exclude(last_activity_at__gt=cutoff_time) + feed.reported_at = now + feed.save()#may not actually report anything, depending on filters below + if feed.feed_type == 'q_sel': + q_sel = Q_set.filter(followed_by=user) + q_sel.cutoff_time = cutoff_time + elif feed.feed_type == 'q_ask': + q_ask = Q_set.filter(author=user) + q_ask.cutoff_time = cutoff_time + elif feed.feed_type == 'q_ans': + q_ans = Q_set.filter(answers__author=user) + q_ans.cutoff_time = cutoff_time + elif feed.feed_type == 'q_all': + q_all = Q_set + q_all.cutoff_time = cutoff_time + #build list in this order + q_tbl = {} + def extend_question_list(src, dst): + if isinstance(src,list): + return + cutoff_time = src.cutoff_time + for q in src: + if q in dst: + if cutoff_time < dst[q]: + dst[q] = cutoff_time + else: + dst[q] = cutoff_time + + extend_question_list(q_sel, q_tbl) + extend_question_list(q_ask, q_tbl) + extend_question_list(q_ans, q_tbl) + extend_question_list(q_all, q_tbl) + + ctype = ContentType.objects.get_for_model(Question) + out = {} + for q, cutoff_time in q_tbl.items(): + #todo use Activity, but first start keeping more Activity records + #act = Activity.objects.filter(content_type=ctype, object_id=q.id) + #get info on question edits, answer edits, comments + out[q] = {} + q_rev = QuestionRevision.objects.filter(question=q,revised_at__lt=cutoff_time) + q_rev = q_rev.exclude(author=user) + out[q]['q_rev'] = len(q_rev) + if len(q_rev) > 0 and q.added_at == q_rev[0].revised_at: + out[q]['q_rev'] = 0 + out[q]['new_q'] = True + else: + out[q]['new_q'] = False + + new_ans = Answer.objects.filter(question=q,added_at__lt=cutoff_time) + new_ans = new_ans.exclude(author=user) + out[q]['new_ans'] = len(new_ans) + ans_rev = AnswerRevision.objects.filter(answer__question=q,revised_at__lt=cutoff_time) + ans_rev = ans_rev.exclude(author=user) + out[q]['ans_rev'] = len(ans_rev) + return out + + def __act_count(self,string,number,output): + if number > 0: + output.append(_(string) % {'num':number}) + def send_email_alerts(self): - report_time = datetime.datetime.now() - feeds = EmailFeed.objects.all() - user_ctype = ContentType.objects.get_for_model(User) - - #lists of update messages keyed by email address - update_collection = collections.defaultdict(list) - for feed in feeds: - update_summary = feed.get_update_summary() - if update_summary != None: - email = feed.get_email() - update_collection[email].append(update_summary) - feed.reported_at = report_time - feed.save() - - for email, updates in update_collection.items(): - text = '\n'.join(updates) - subject = _('updates from website') - print 'sent %s to %s' % (updates,email) - msg = EmailMessage(subject, text, settings.DEFAULT_FROM_EMAIL, [email]) - msg.content_subtype = 'html' - msg.send() - - + + for user in User.objects.all(): + q_list = self.get_updated_questions_for_user(user) + num_q = len(q_list) + if num_q > 0: + url_prefix = settings.APP_URL + subject = _('email update message subject') + text = ungettext('%(name)s, this is an update message header for a question', + '%(name)s, this is an update message header for %(num)d questions',num_q) \ + % {'num':num_q, 'name':user.username} + + text += '' + 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]} + msg = EmailMessage(subject, text, settings.DEFAULT_FROM_EMAIL, [user.email]) + msg.content_subtype = 'html' + msg.send() -- cgit v1.2.3-1-g7c22 From 59e445ae892cea104a7d5354027c72c60294815a Mon Sep 17 00:00:00 2001 From: Evgeny Fadeev Date: Mon, 23 Nov 2009 21:16:31 -0500 Subject: improved email subscription job, some small fixes, users now can change their screen name any time --- forum/management/commands/send_email_alerts.py | 134 +++++++++++++++++-------- 1 file changed, 93 insertions(+), 41 deletions(-) (limited to 'forum/management/commands/send_email_alerts.py') diff --git a/forum/management/commands/send_email_alerts.py b/forum/management/commands/send_email_alerts.py index a25e4343..8d52ed64 100644 --- a/forum/management/commands/send_email_alerts.py +++ b/forum/management/commands/send_email_alerts.py @@ -2,11 +2,14 @@ from django.core.management.base import NoArgsCommand from django.db import connection from django.db.models import Q, F from forum.models import * +from forum import const from django.core.mail import EmailMessage from django.utils.translation import ugettext as _ from django.utils.translation import ungettext import datetime import settings +import logging +from utils.odict import OrderedDict class Command(NoArgsCommand): def handle_noargs(self,**options): @@ -18,10 +21,10 @@ class Command(NoArgsCommand): connection.close() def get_updated_questions_for_user(self,user): - q_sel = [] - q_ask = [] - q_ans = [] - q_all = [] + q_sel = None + q_ask = None + q_ans = None + q_all = None now = datetime.datetime.now() Q_set1 = Question.objects.exclude( last_activity_by=user, @@ -39,12 +42,12 @@ class Command(NoArgsCommand): for feed in user_feeds: cutoff_time = now - EmailFeedSetting.DELTA_TABLE[feed.frequency] if feed.reported_at == None or feed.reported_at <= cutoff_time: - Q_set = Q_set1.exclude(last_activity_at__gt=cutoff_time) + Q_set = Q_set1.exclude(last_activity_at__gt=cutoff_time)#report these excluded later feed.reported_at = now feed.save()#may not actually report anything, depending on filters below if feed.feed_type == 'q_sel': q_sel = Q_set.filter(followed_by=user) - q_sel.cutoff_time = cutoff_time + q_sel.cutoff_time = cutoff_time #store cutoff time per query set elif feed.feed_type == 'q_ask': q_ask = Q_set.filter(author=user) q_ask.cutoff_time = cutoff_time @@ -55,56 +58,92 @@ class Command(NoArgsCommand): q_all = Q_set q_all.cutoff_time = cutoff_time #build list in this order - q_tbl = {} + q_list = OrderedDict() def extend_question_list(src, dst): - if isinstance(src,list): - return + """src is a query set with questions + or an empty list + dst - is an ordered dictionary + """ + if src is None: + return #will not do anything if subscription of this type is not used cutoff_time = src.cutoff_time for q in src: if q in dst: - if cutoff_time < dst[q]: - dst[q] = cutoff_time + if cutoff_time < dst[q]['cutoff_time']: + dst[q]['cutoff_time'] = cutoff_time else: - dst[q] = cutoff_time + #initialise a questions metadata dictionary to use for email reporting + dst[q] = {'cutoff_time':cutoff_time} - extend_question_list(q_sel, q_tbl) - extend_question_list(q_ask, q_tbl) - extend_question_list(q_ans, q_tbl) - extend_question_list(q_all, q_tbl) + extend_question_list(q_sel, q_list) + extend_question_list(q_ask, q_list) + extend_question_list(q_ans, q_list) + extend_question_list(q_all, q_list) ctype = ContentType.objects.get_for_model(Question) - out = {} - for q, cutoff_time in q_tbl.items(): + EMAIL_UPDATE_ACTIVITY = const.TYPE_ACTIVITY_QUESTION_EMAIL_UPDATE_SENT + for q, meta_data in q_list.items(): #todo use Activity, but first start keeping more Activity records #act = Activity.objects.filter(content_type=ctype, object_id=q.id) - #get info on question edits, answer edits, comments - out[q] = {} - q_rev = QuestionRevision.objects.filter(question=q,revised_at__lt=cutoff_time) + #because currently activity is not fully recorded to through + #revision records to see what kind modifications were done on + #the questions and answers + try: + update_info = Activity.objects.get(content_type=ctype, + object_id=q.id, + activity_type=EMAIL_UPDATE_ACTIVITY) + emailed_at = update_info.active_at + except Activity.DoesNotExist: + update_info = Activity(user=user, content_object=q, activity_type=EMAIL_UPDATE_ACTIVITY) + emailed_at = datetime.datetime(1970,1,1)#long time ago + except Activity.MultipleObjectsReturned: + raise Exception('server error - multiple question email activities found per user-question pair') + + q_rev = QuestionRevision.objects.filter(question=q,\ + revised_at__lt=cutoff_time,\ + revised_at__gt=emailed_at) q_rev = q_rev.exclude(author=user) - out[q]['q_rev'] = len(q_rev) + meta_data['q_rev'] = len(q_rev) if len(q_rev) > 0 and q.added_at == q_rev[0].revised_at: - out[q]['q_rev'] = 0 - out[q]['new_q'] = True + meta_data['q_rev'] = 0 + meta_data['new_q'] = True else: - out[q]['new_q'] = False + meta_data['new_q'] = False - new_ans = Answer.objects.filter(question=q,added_at__lt=cutoff_time) + new_ans = Answer.objects.filter(question=q,\ + added_at__lt=cutoff_time,\ + added_at__gt=emailed_at) new_ans = new_ans.exclude(author=user) - out[q]['new_ans'] = len(new_ans) - ans_rev = AnswerRevision.objects.filter(answer__question=q,revised_at__lt=cutoff_time) + meta_data['new_ans'] = len(new_ans) + ans_rev = AnswerRevision.objects.filter(answer__question=q,\ + revised_at__lt=cutoff_time,\ + revised_at__gt=emailed_at) ans_rev = ans_rev.exclude(author=user) - out[q]['ans_rev'] = len(ans_rev) - return out + meta_data['ans_rev'] = len(ans_rev) + if len(q_rev) == 0 and len(new_ans) == 0 and len(ans_rev) == 0: + meta_data['nothing_new'] = True + else: + meta_data['nothing_new'] = False + update_info.active_at = now + update_info.save() #save question email update activity + return q_list - def __act_count(self,string,number,output): + def __action_count(self,string,number,output): if number > 0: output.append(_(string) % {'num':number}) def send_email_alerts(self): + #todo: move this to template for user in User.objects.all(): q_list = self.get_updated_questions_for_user(user) - num_q = len(q_list) + num_q = 0 + num_moot = 0 + for meta_data in q_list.values(): + if meta_data['nothing_new'] == False: + num_q += 1 + else: + num_moot += 1 if num_q > 0: url_prefix = settings.APP_URL subject = _('email update message subject') @@ -113,17 +152,30 @@ class Command(NoArgsCommand): % {'num':num_q, 'name':user.username} text += '
    ' - for q, act in q_list.items(): + for q, meta_data in q_list.items(): act_list = [] - if act['new_q']: - act_list.append(_('new question')) - self.__act_count('%(num)d rev', act['q_rev'],act_list) - self.__act_count('%(num)d ans', act['new_ans'],act_list) - self.__act_count('%(num)d ans rev',act['ans_rev'],act_list) - act_token = ', '.join(act_list) - text += '
  • %s (%s)
  • ' \ - % (url_prefix + q.get_absolute_url(), q.title, act_token) + if meta_data['nothing_new']: + continue + else: + if meta_data['new_q']: + act_list.append(_('new question')) + self.__action_count('%(num)d rev', meta_data['q_rev'],act_list) + self.__action_count('%(num)d ans', meta_data['new_ans'],act_list) + self.__action_count('%(num)d ans rev',meta_data['ans_rev'],act_list) + act_token = ', '.join(act_list) + text += '
  • %s (%s)
  • ' \ + % (url_prefix + q.get_absolute_url(), q.title, act_token) text += '
' + if num_moot > 0: + text += '

' + text += ungettext('There is also one question which was recently '\ + +'updated but you might not have seen its latest version.', + 'There are also %(num)d more questions which were recently updated '\ + +'but you might not have seen their latest version.',num_moot) \ + % {'num':num_moot,} + text += _('Perhaps you could look up previously sent forum reminders in your mailbox.') + text += '

' + 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]} -- cgit v1.2.3-1-g7c22 From 86250a6d49e69ff04d128d11bfa82d9a7b345bbf Mon Sep 17 00:00:00 2001 From: Evgeny Fadeev Date: Tue, 8 Dec 2009 22:50:21 -0500 Subject: added interesting and ignored tag selectors (works) and per-tag subscription (not tested yet) --- forum/management/commands/send_email_alerts.py | 139 +++++++++++++------------ 1 file changed, 75 insertions(+), 64 deletions(-) (limited to 'forum/management/commands/send_email_alerts.py') diff --git a/forum/management/commands/send_email_alerts.py b/forum/management/commands/send_email_alerts.py index 8d52ed64..563aab69 100644 --- a/forum/management/commands/send_email_alerts.py +++ b/forum/management/commands/send_email_alerts.py @@ -38,73 +38,84 @@ class Command(NoArgsCommand): ).exclude( closed=True ) - user_feeds = EmailFeedSetting.objects.filter(subscriber=user).exclude(frequency='n') - for feed in user_feeds: - cutoff_time = now - EmailFeedSetting.DELTA_TABLE[feed.frequency] - if feed.reported_at == None or feed.reported_at <= cutoff_time: - Q_set = Q_set1.exclude(last_activity_at__gt=cutoff_time)#report these excluded later - feed.reported_at = now - feed.save()#may not actually report anything, depending on filters below - if feed.feed_type == 'q_sel': - q_sel = Q_set.filter(followed_by=user) - q_sel.cutoff_time = cutoff_time #store cutoff time per query set - elif feed.feed_type == 'q_ask': - q_ask = Q_set.filter(author=user) - q_ask.cutoff_time = cutoff_time - elif feed.feed_type == 'q_ans': - q_ans = Q_set.filter(answers__author=user) - q_ans.cutoff_time = cutoff_time - elif feed.feed_type == 'q_all': - q_all = Q_set - q_all.cutoff_time = cutoff_time - #build list in this order - q_list = OrderedDict() - def extend_question_list(src, dst): - """src is a query set with questions - or an empty list - dst - is an ordered dictionary - """ - if src is None: - return #will not do anything if subscription of this type is not used - cutoff_time = src.cutoff_time - for q in src: - if q in dst: - if cutoff_time < dst[q]['cutoff_time']: - dst[q]['cutoff_time'] = cutoff_time - else: - #initialise a questions metadata dictionary to use for email reporting - dst[q] = {'cutoff_time':cutoff_time} + #todo: still need to add back individually selected and other questions.... + #these may be filtered out by tags + if user.tag_filter_setting == 'ignored': + ignored_tags = user.markedtag_set.filter(reason='bad').values_list('tag', flat=True).distinct() + Q_set1 = Q_set1.exclude( tags__in=ignored_tags ) + logging.debug('removed ignored tags') + else: + selected_tags = user.markedtag_set.filter(reason='good').values_list('tag', flat=True).distinct() + Q_set1 = Q_set1.filter( tags__in=selected_tags ) + logging.debug('filtered for only selected tags') + + user_feeds = EmailFeedSetting.objects.filter(subscriber=user).exclude(frequency='n') + for feed in user_feeds: + cutoff_time = now - EmailFeedSetting.DELTA_TABLE[feed.frequency] + if feed.reported_at == None or feed.reported_at <= cutoff_time: + Q_set = Q_set1.exclude(last_activity_at__gt=cutoff_time)#report these excluded later + feed.reported_at = now + feed.save()#may not actually report anything, depending on filters below + if feed.feed_type == 'q_sel': + q_sel = Q_set.filter(followed_by=user) + q_sel.cutoff_time = cutoff_time #store cutoff time per query set + elif feed.feed_type == 'q_ask': + q_ask = Q_set.filter(author=user) + q_ask.cutoff_time = cutoff_time + elif feed.feed_type == 'q_ans': + q_ans = Q_set.filter(answers__author=user) + q_ans.cutoff_time = cutoff_time + elif feed.feed_type == 'q_all': + q_all = Q_set + q_all.cutoff_time = cutoff_time + #build list in this order + q_list = OrderedDict() + def extend_question_list(src, dst): + """src is a query set with questions + or an empty list + dst - is an ordered dictionary + """ + if src is None: + return #will not do anything if subscription of this type is not used + cutoff_time = src.cutoff_time + for q in src: + if q in dst: + if cutoff_time < dst[q]['cutoff_time']: + dst[q]['cutoff_time'] = cutoff_time + else: + #initialise a questions metadata dictionary to use for email reporting + dst[q] = {'cutoff_time':cutoff_time} - extend_question_list(q_sel, q_list) - extend_question_list(q_ask, q_list) - extend_question_list(q_ans, q_list) - extend_question_list(q_all, q_list) + extend_question_list(q_sel, q_list) + extend_question_list(q_ask, q_list) + extend_question_list(q_ans, q_list) + extend_question_list(q_all, q_list) - ctype = ContentType.objects.get_for_model(Question) - EMAIL_UPDATE_ACTIVITY = const.TYPE_ACTIVITY_QUESTION_EMAIL_UPDATE_SENT - for q, meta_data in q_list.items(): - #todo use Activity, but first start keeping more Activity records - #act = Activity.objects.filter(content_type=ctype, object_id=q.id) - #because currently activity is not fully recorded to through - #revision records to see what kind modifications were done on - #the questions and answers - try: - update_info = Activity.objects.get(content_type=ctype, - object_id=q.id, - activity_type=EMAIL_UPDATE_ACTIVITY) - emailed_at = update_info.active_at - except Activity.DoesNotExist: - update_info = Activity(user=user, content_object=q, activity_type=EMAIL_UPDATE_ACTIVITY) - emailed_at = datetime.datetime(1970,1,1)#long time ago - except Activity.MultipleObjectsReturned: - raise Exception('server error - multiple question email activities found per user-question pair') + ctype = ContentType.objects.get_for_model(Question) + EMAIL_UPDATE_ACTIVITY = const.TYPE_ACTIVITY_QUESTION_EMAIL_UPDATE_SENT + for q, meta_data in q_list.items(): + #todo use Activity, but first start keeping more Activity records + #act = Activity.objects.filter(content_type=ctype, object_id=q.id) + #because currently activity is not fully recorded to through + #revision records to see what kind modifications were done on + #the questions and answers + try: + update_info = Activity.objects.get(content_type=ctype, + object_id=q.id, + activity_type=EMAIL_UPDATE_ACTIVITY) + emailed_at = update_info.active_at + except Activity.DoesNotExist: + update_info = Activity(user=user, content_object=q, activity_type=EMAIL_UPDATE_ACTIVITY) + emailed_at = datetime.datetime(1970,1,1)#long time ago + except Activity.MultipleObjectsReturned: + raise Exception('server error - multiple question email activities found per user-question pair') - q_rev = QuestionRevision.objects.filter(question=q,\ - revised_at__lt=cutoff_time,\ - revised_at__gt=emailed_at) - q_rev = q_rev.exclude(author=user) - meta_data['q_rev'] = len(q_rev) - if len(q_rev) > 0 and q.added_at == q_rev[0].revised_at: + q_rev = QuestionRevision.objects.filter(question=q,\ + revised_at__lt=cutoff_time,\ + revised_at__gt=emailed_at) + q_rev = q_rev.exclude(author=user) + meta_data['q_rev'] = len(q_rev) + if len(q_rev) > 0 and q.added_at == q_rev[0].revised_at: meta_data['q_rev'] = 0 meta_data['new_q'] = True else: -- cgit v1.2.3-1-g7c22 From 368c62b96a13d4fc340c67bbfc4048e227269070 Mon Sep 17 00:00:00 2001 From: Evgeny Fadeev Date: Wed, 9 Dec 2009 12:13:08 -0500 Subject: better selector of ignored questions, split javascript tag_selector into separate file, fixed question counter messages in the english lang file --- forum/management/commands/send_email_alerts.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'forum/management/commands/send_email_alerts.py') diff --git a/forum/management/commands/send_email_alerts.py b/forum/management/commands/send_email_alerts.py index 563aab69..4a636e87 100644 --- a/forum/management/commands/send_email_alerts.py +++ b/forum/management/commands/send_email_alerts.py @@ -41,11 +41,11 @@ class Command(NoArgsCommand): #todo: still need to add back individually selected and other questions.... #these may be filtered out by tags if user.tag_filter_setting == 'ignored': - ignored_tags = user.markedtag_set.filter(reason='bad').values_list('tag', flat=True).distinct() + ignored_tags = Tag.objects.filter(user_selections___reason='bad',user_selections__user=user) Q_set1 = Q_set1.exclude( tags__in=ignored_tags ) logging.debug('removed ignored tags') else: - selected_tags = user.markedtag_set.filter(reason='good').values_list('tag', flat=True).distinct() + selected_tags = Tag.objects.filter(user_selections___reason='good',user_selections__user=user) Q_set1 = Q_set1.filter( tags__in=selected_tags ) logging.debug('filtered for only selected tags') -- cgit v1.2.3-1-g7c22 From 5841b2c222f6cca42ba793d5360f8ab704c61adc Mon Sep 17 00:00:00 2001 From: Evgeny Fadeev Date: Wed, 9 Dec 2009 19:57:25 -0500 Subject: added sitemap at /sitemap.xml and fixed per tag subscription (hopefully) --- forum/management/commands/send_email_alerts.py | 145 ++++++++++++------------- 1 file changed, 70 insertions(+), 75 deletions(-) (limited to 'forum/management/commands/send_email_alerts.py') diff --git a/forum/management/commands/send_email_alerts.py b/forum/management/commands/send_email_alerts.py index 4a636e87..777381ec 100644 --- a/forum/management/commands/send_email_alerts.py +++ b/forum/management/commands/send_email_alerts.py @@ -38,84 +38,79 @@ class Command(NoArgsCommand): ).exclude( closed=True ) - #todo: still need to add back individually selected and other questions.... - #these may be filtered out by tags - if user.tag_filter_setting == 'ignored': - ignored_tags = Tag.objects.filter(user_selections___reason='bad',user_selections__user=user) - Q_set1 = Q_set1.exclude( tags__in=ignored_tags ) - logging.debug('removed ignored tags') - else: - selected_tags = Tag.objects.filter(user_selections___reason='good',user_selections__user=user) - Q_set1 = Q_set1.filter( tags__in=selected_tags ) - logging.debug('filtered for only selected tags') - - user_feeds = EmailFeedSetting.objects.filter(subscriber=user).exclude(frequency='n') - for feed in user_feeds: - cutoff_time = now - EmailFeedSetting.DELTA_TABLE[feed.frequency] - if feed.reported_at == None or feed.reported_at <= cutoff_time: - Q_set = Q_set1.exclude(last_activity_at__gt=cutoff_time)#report these excluded later - feed.reported_at = now - feed.save()#may not actually report anything, depending on filters below - if feed.feed_type == 'q_sel': - q_sel = Q_set.filter(followed_by=user) - q_sel.cutoff_time = cutoff_time #store cutoff time per query set - elif feed.feed_type == 'q_ask': - q_ask = Q_set.filter(author=user) - q_ask.cutoff_time = cutoff_time - elif feed.feed_type == 'q_ans': - q_ans = Q_set.filter(answers__author=user) - q_ans.cutoff_time = cutoff_time - elif feed.feed_type == 'q_all': - q_all = Q_set - q_all.cutoff_time = cutoff_time - #build list in this order - q_list = OrderedDict() - def extend_question_list(src, dst): - """src is a query set with questions - or an empty list - dst - is an ordered dictionary - """ - if src is None: - return #will not do anything if subscription of this type is not used - cutoff_time = src.cutoff_time - for q in src: - if q in dst: - if cutoff_time < dst[q]['cutoff_time']: - dst[q]['cutoff_time'] = cutoff_time - else: - #initialise a questions metadata dictionary to use for email reporting - dst[q] = {'cutoff_time':cutoff_time} + + user_feeds = EmailFeedSetting.objects.filter(subscriber=user).exclude(frequency='n') + for feed in user_feeds: + cutoff_time = now - EmailFeedSetting.DELTA_TABLE[feed.frequency] + if feed.reported_at == None or feed.reported_at <= cutoff_time: + Q_set = Q_set1.exclude(last_activity_at__gt=cutoff_time)#report these excluded later + feed.reported_at = now + feed.save()#may not actually report anything, depending on filters below + if feed.feed_type == 'q_sel': + q_sel = Q_set.filter(followed_by=user) + q_sel.cutoff_time = cutoff_time #store cutoff time per query set + elif feed.feed_type == 'q_ask': + q_ask = Q_set.filter(author=user) + q_ask.cutoff_time = cutoff_time + elif feed.feed_type == 'q_ans': + q_ans = Q_set.filter(answers__author=user) + q_ans.cutoff_time = cutoff_time + elif feed.feed_type == 'q_all': + if user.tag_filter_setting == 'ignored': + ignored_tags = Tag.objects.filter(user_selections___reason='bad',user_selections__user=user) + q_all = Q_set.exclude( tags__in=ignored_tags ) + else: + selected_tags = Tag.objects.filter(user_selections___reason='good',user_selections__user=user) + q_all = Q_set.filter( tags__in=selected_tags ) + q_all.cutoff_time = cutoff_time + #build list in this order + q_list = OrderedDict() + def extend_question_list(src, dst): + """src is a query set with questions + or an empty list + dst - is an ordered dictionary + """ + if src is None: + return #will not do anything if subscription of this type is not used + cutoff_time = src.cutoff_time + for q in src: + if q in dst: + if cutoff_time < dst[q]['cutoff_time']: + dst[q]['cutoff_time'] = cutoff_time + else: + #initialise a questions metadata dictionary to use for email reporting + dst[q] = {'cutoff_time':cutoff_time} - extend_question_list(q_sel, q_list) - extend_question_list(q_ask, q_list) - extend_question_list(q_ans, q_list) - extend_question_list(q_all, q_list) + extend_question_list(q_sel, q_list) + extend_question_list(q_ask, q_list) + extend_question_list(q_ans, q_list) + extend_question_list(q_all, q_list) - ctype = ContentType.objects.get_for_model(Question) - EMAIL_UPDATE_ACTIVITY = const.TYPE_ACTIVITY_QUESTION_EMAIL_UPDATE_SENT - for q, meta_data in q_list.items(): - #todo use Activity, but first start keeping more Activity records - #act = Activity.objects.filter(content_type=ctype, object_id=q.id) - #because currently activity is not fully recorded to through - #revision records to see what kind modifications were done on - #the questions and answers - try: - update_info = Activity.objects.get(content_type=ctype, - object_id=q.id, - activity_type=EMAIL_UPDATE_ACTIVITY) - emailed_at = update_info.active_at - except Activity.DoesNotExist: - update_info = Activity(user=user, content_object=q, activity_type=EMAIL_UPDATE_ACTIVITY) - emailed_at = datetime.datetime(1970,1,1)#long time ago - except Activity.MultipleObjectsReturned: - raise Exception('server error - multiple question email activities found per user-question pair') + ctype = ContentType.objects.get_for_model(Question) + EMAIL_UPDATE_ACTIVITY = const.TYPE_ACTIVITY_QUESTION_EMAIL_UPDATE_SENT + for q, meta_data in q_list.items(): + #todo use Activity, but first start keeping more Activity records + #act = Activity.objects.filter(content_type=ctype, object_id=q.id) + #because currently activity is not fully recorded to through + #revision records to see what kind modifications were done on + #the questions and answers + try: + update_info = Activity.objects.get(content_type=ctype, + object_id=q.id, + activity_type=EMAIL_UPDATE_ACTIVITY) + emailed_at = update_info.active_at + except Activity.DoesNotExist: + update_info = Activity(user=user, content_object=q, activity_type=EMAIL_UPDATE_ACTIVITY) + emailed_at = datetime.datetime(1970,1,1)#long time ago + except Activity.MultipleObjectsReturned: + raise Exception('server error - multiple question email activities found per user-question pair') - q_rev = QuestionRevision.objects.filter(question=q,\ - revised_at__lt=cutoff_time,\ - revised_at__gt=emailed_at) - q_rev = q_rev.exclude(author=user) - meta_data['q_rev'] = len(q_rev) - if len(q_rev) > 0 and q.added_at == q_rev[0].revised_at: + q_rev = QuestionRevision.objects.filter(question=q,\ + revised_at__lt=cutoff_time,\ + revised_at__gt=emailed_at) + q_rev = q_rev.exclude(author=user) + meta_data['q_rev'] = len(q_rev) + if len(q_rev) > 0 and q.added_at == q_rev[0].revised_at: meta_data['q_rev'] = 0 meta_data['new_q'] = True else: -- cgit v1.2.3-1-g7c22 From ab7193ae3ca32958fa64cd5222919a4ca95a33c1 Mon Sep 17 00:00:00 2001 From: Rick Ross Date: Sat, 16 Jan 2010 08:29:11 -0500 Subject: modified try-except-finally blocks for python 2.4 compatibility --- forum/management/commands/send_email_alerts.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'forum/management/commands/send_email_alerts.py') diff --git a/forum/management/commands/send_email_alerts.py b/forum/management/commands/send_email_alerts.py index 777381ec..f5974e6b 100644 --- a/forum/management/commands/send_email_alerts.py +++ b/forum/management/commands/send_email_alerts.py @@ -14,9 +14,10 @@ from utils.odict import OrderedDict class Command(NoArgsCommand): def handle_noargs(self,**options): try: - self.send_email_alerts() - except Exception, e: - print e + try: + self.send_email_alerts() + except Exception, e: + print e finally: connection.close() -- cgit v1.2.3-1-g7c22 From 2156804d24b5a8a877f1ea36674ac7fe078be9a0 Mon Sep 17 00:00:00 2001 From: Evgeny Fadeev Date: Sun, 24 Jan 2010 19:53:00 -0500 Subject: recaptcha for conventional registration\n\ simpler email subscription form at registration\n\ fixed urls in rss feed\n\ added experimental remote password login api (cleartext password for remote site entered locally)\n\ included example for Mediawiki Authentication plugin\n\ very simple message to everyone management command --- forum/management/commands/send_email_alerts.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'forum/management/commands/send_email_alerts.py') diff --git a/forum/management/commands/send_email_alerts.py b/forum/management/commands/send_email_alerts.py index f5974e6b..62f13d69 100644 --- a/forum/management/commands/send_email_alerts.py +++ b/forum/management/commands/send_email_alerts.py @@ -7,7 +7,7 @@ from django.core.mail import EmailMessage from django.utils.translation import ugettext as _ from django.utils.translation import ungettext import datetime -import settings +from django.conf import settings import logging from utils.odict import OrderedDict @@ -58,10 +58,10 @@ class Command(NoArgsCommand): q_ans.cutoff_time = cutoff_time elif feed.feed_type == 'q_all': if user.tag_filter_setting == 'ignored': - ignored_tags = Tag.objects.filter(user_selections___reason='bad',user_selections__user=user) + ignored_tags = Tag.objects.filter(user_selections__reason='bad',user_selections__user=user) q_all = Q_set.exclude( tags__in=ignored_tags ) else: - selected_tags = Tag.objects.filter(user_selections___reason='good',user_selections__user=user) + selected_tags = Tag.objects.filter(user_selections__reason='good',user_selections__user=user) q_all = Q_set.filter( tags__in=selected_tags ) q_all.cutoff_time = cutoff_time #build list in this order @@ -154,6 +154,7 @@ class Command(NoArgsCommand): if num_q > 0: url_prefix = settings.APP_URL subject = _('email update message subject') + print 'have %d updated questions for %s' % (num_q, user.username) text = ungettext('%(name)s, this is an update message header for a question', '%(name)s, this is an update message header for %(num)d questions',num_q) \ % {'num':num_q, 'name':user.username} -- cgit v1.2.3-1-g7c22 From abc5fe0302f513848ec50dd8e8cbf4754bb7f841 Mon Sep 17 00:00:00 2001 From: Joseph Turian Date: Sun, 7 Feb 2010 22:57:47 -0500 Subject: Moved applications into apps/ directory --- forum/management/commands/send_email_alerts.py | 192 ------------------------- 1 file changed, 192 deletions(-) delete mode 100644 forum/management/commands/send_email_alerts.py (limited to 'forum/management/commands/send_email_alerts.py') diff --git a/forum/management/commands/send_email_alerts.py b/forum/management/commands/send_email_alerts.py deleted file mode 100644 index 62f13d69..00000000 --- a/forum/management/commands/send_email_alerts.py +++ /dev/null @@ -1,192 +0,0 @@ -from django.core.management.base import NoArgsCommand -from django.db import connection -from django.db.models import Q, F -from forum.models import * -from forum import const -from django.core.mail import EmailMessage -from django.utils.translation import ugettext as _ -from django.utils.translation import ungettext -import datetime -from django.conf import settings -import logging -from utils.odict import OrderedDict - -class Command(NoArgsCommand): - def handle_noargs(self,**options): - try: - try: - self.send_email_alerts() - except Exception, e: - print e - finally: - connection.close() - - def get_updated_questions_for_user(self,user): - q_sel = None - q_ask = None - q_ans = None - q_all = None - now = datetime.datetime.now() - Q_set1 = Question.objects.exclude( - last_activity_by=user, - ).exclude( - last_activity_at__lt=user.date_joined - ).filter( - Q(viewed__who=user,viewed__when__lt=F('last_activity_at')) | \ - ~Q(viewed__who=user) - ).exclude( - deleted=True - ).exclude( - closed=True - ) - - user_feeds = EmailFeedSetting.objects.filter(subscriber=user).exclude(frequency='n') - for feed in user_feeds: - cutoff_time = now - EmailFeedSetting.DELTA_TABLE[feed.frequency] - if feed.reported_at == None or feed.reported_at <= cutoff_time: - Q_set = Q_set1.exclude(last_activity_at__gt=cutoff_time)#report these excluded later - feed.reported_at = now - feed.save()#may not actually report anything, depending on filters below - if feed.feed_type == 'q_sel': - q_sel = Q_set.filter(followed_by=user) - q_sel.cutoff_time = cutoff_time #store cutoff time per query set - elif feed.feed_type == 'q_ask': - q_ask = Q_set.filter(author=user) - q_ask.cutoff_time = cutoff_time - elif feed.feed_type == 'q_ans': - q_ans = Q_set.filter(answers__author=user) - q_ans.cutoff_time = cutoff_time - elif feed.feed_type == 'q_all': - if user.tag_filter_setting == 'ignored': - ignored_tags = Tag.objects.filter(user_selections__reason='bad',user_selections__user=user) - q_all = Q_set.exclude( tags__in=ignored_tags ) - else: - selected_tags = Tag.objects.filter(user_selections__reason='good',user_selections__user=user) - q_all = Q_set.filter( tags__in=selected_tags ) - q_all.cutoff_time = cutoff_time - #build list in this order - q_list = OrderedDict() - def extend_question_list(src, dst): - """src is a query set with questions - or an empty list - dst - is an ordered dictionary - """ - if src is None: - return #will not do anything if subscription of this type is not used - cutoff_time = src.cutoff_time - for q in src: - if q in dst: - if cutoff_time < dst[q]['cutoff_time']: - dst[q]['cutoff_time'] = cutoff_time - else: - #initialise a questions metadata dictionary to use for email reporting - dst[q] = {'cutoff_time':cutoff_time} - - extend_question_list(q_sel, q_list) - extend_question_list(q_ask, q_list) - extend_question_list(q_ans, q_list) - extend_question_list(q_all, q_list) - - ctype = ContentType.objects.get_for_model(Question) - EMAIL_UPDATE_ACTIVITY = const.TYPE_ACTIVITY_QUESTION_EMAIL_UPDATE_SENT - for q, meta_data in q_list.items(): - #todo use Activity, but first start keeping more Activity records - #act = Activity.objects.filter(content_type=ctype, object_id=q.id) - #because currently activity is not fully recorded to through - #revision records to see what kind modifications were done on - #the questions and answers - try: - update_info = Activity.objects.get(content_type=ctype, - object_id=q.id, - activity_type=EMAIL_UPDATE_ACTIVITY) - emailed_at = update_info.active_at - except Activity.DoesNotExist: - update_info = Activity(user=user, content_object=q, activity_type=EMAIL_UPDATE_ACTIVITY) - emailed_at = datetime.datetime(1970,1,1)#long time ago - except Activity.MultipleObjectsReturned: - raise Exception('server error - multiple question email activities found per user-question pair') - - q_rev = QuestionRevision.objects.filter(question=q,\ - revised_at__lt=cutoff_time,\ - revised_at__gt=emailed_at) - q_rev = q_rev.exclude(author=user) - meta_data['q_rev'] = len(q_rev) - if len(q_rev) > 0 and q.added_at == q_rev[0].revised_at: - meta_data['q_rev'] = 0 - meta_data['new_q'] = True - else: - meta_data['new_q'] = False - - new_ans = Answer.objects.filter(question=q,\ - added_at__lt=cutoff_time,\ - added_at__gt=emailed_at) - new_ans = new_ans.exclude(author=user) - meta_data['new_ans'] = len(new_ans) - ans_rev = AnswerRevision.objects.filter(answer__question=q,\ - revised_at__lt=cutoff_time,\ - revised_at__gt=emailed_at) - ans_rev = ans_rev.exclude(author=user) - meta_data['ans_rev'] = len(ans_rev) - if len(q_rev) == 0 and len(new_ans) == 0 and len(ans_rev) == 0: - meta_data['nothing_new'] = True - else: - meta_data['nothing_new'] = False - update_info.active_at = now - update_info.save() #save question email update activity - return q_list - - def __action_count(self,string,number,output): - if number > 0: - output.append(_(string) % {'num':number}) - - def send_email_alerts(self): - - #todo: move this to template - for user in User.objects.all(): - q_list = self.get_updated_questions_for_user(user) - num_q = 0 - num_moot = 0 - for meta_data in q_list.values(): - if meta_data['nothing_new'] == False: - num_q += 1 - else: - num_moot += 1 - if num_q > 0: - url_prefix = settings.APP_URL - subject = _('email update message subject') - print 'have %d updated questions for %s' % (num_q, user.username) - text = ungettext('%(name)s, this is an update message header for a question', - '%(name)s, this is an update message header for %(num)d questions',num_q) \ - % {'num':num_q, 'name':user.username} - - text += '
    ' - for q, meta_data in q_list.items(): - act_list = [] - if meta_data['nothing_new']: - continue - else: - if meta_data['new_q']: - act_list.append(_('new question')) - self.__action_count('%(num)d rev', meta_data['q_rev'],act_list) - self.__action_count('%(num)d ans', meta_data['new_ans'],act_list) - self.__action_count('%(num)d ans rev',meta_data['ans_rev'],act_list) - act_token = ', '.join(act_list) - text += '
  • %s (%s)
  • ' \ - % (url_prefix + q.get_absolute_url(), q.title, act_token) - text += '
' - if num_moot > 0: - text += '

' - text += ungettext('There is also one question which was recently '\ - +'updated but you might not have seen its latest version.', - 'There are also %(num)d more questions which were recently updated '\ - +'but you might not have seen their latest version.',num_moot) \ - % {'num':num_moot,} - text += _('Perhaps you could look up previously sent forum reminders in your mailbox.') - text += '

' - - 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]} - msg = EmailMessage(subject, text, settings.DEFAULT_FROM_EMAIL, [user.email]) - msg.content_subtype = 'html' - msg.send() -- cgit v1.2.3-1-g7c22 From b2d9fb47fd657d2da515d7bb88bcc0fb2a9b5785 Mon Sep 17 00:00:00 2001 From: Joseph Turian Date: Sun, 7 Feb 2010 23:55:58 -0500 Subject: Moved apps back into base dir --- forum/management/commands/send_email_alerts.py | 192 +++++++++++++++++++++++++ 1 file changed, 192 insertions(+) create mode 100644 forum/management/commands/send_email_alerts.py (limited to 'forum/management/commands/send_email_alerts.py') diff --git a/forum/management/commands/send_email_alerts.py b/forum/management/commands/send_email_alerts.py new file mode 100644 index 00000000..62f13d69 --- /dev/null +++ b/forum/management/commands/send_email_alerts.py @@ -0,0 +1,192 @@ +from django.core.management.base import NoArgsCommand +from django.db import connection +from django.db.models import Q, F +from forum.models import * +from forum import const +from django.core.mail import EmailMessage +from django.utils.translation import ugettext as _ +from django.utils.translation import ungettext +import datetime +from django.conf import settings +import logging +from utils.odict import OrderedDict + +class Command(NoArgsCommand): + def handle_noargs(self,**options): + try: + try: + self.send_email_alerts() + except Exception, e: + print e + finally: + connection.close() + + def get_updated_questions_for_user(self,user): + q_sel = None + q_ask = None + q_ans = None + q_all = None + now = datetime.datetime.now() + Q_set1 = Question.objects.exclude( + last_activity_by=user, + ).exclude( + last_activity_at__lt=user.date_joined + ).filter( + Q(viewed__who=user,viewed__when__lt=F('last_activity_at')) | \ + ~Q(viewed__who=user) + ).exclude( + deleted=True + ).exclude( + closed=True + ) + + user_feeds = EmailFeedSetting.objects.filter(subscriber=user).exclude(frequency='n') + for feed in user_feeds: + cutoff_time = now - EmailFeedSetting.DELTA_TABLE[feed.frequency] + if feed.reported_at == None or feed.reported_at <= cutoff_time: + Q_set = Q_set1.exclude(last_activity_at__gt=cutoff_time)#report these excluded later + feed.reported_at = now + feed.save()#may not actually report anything, depending on filters below + if feed.feed_type == 'q_sel': + q_sel = Q_set.filter(followed_by=user) + q_sel.cutoff_time = cutoff_time #store cutoff time per query set + elif feed.feed_type == 'q_ask': + q_ask = Q_set.filter(author=user) + q_ask.cutoff_time = cutoff_time + elif feed.feed_type == 'q_ans': + q_ans = Q_set.filter(answers__author=user) + q_ans.cutoff_time = cutoff_time + elif feed.feed_type == 'q_all': + if user.tag_filter_setting == 'ignored': + ignored_tags = Tag.objects.filter(user_selections__reason='bad',user_selections__user=user) + q_all = Q_set.exclude( tags__in=ignored_tags ) + else: + selected_tags = Tag.objects.filter(user_selections__reason='good',user_selections__user=user) + q_all = Q_set.filter( tags__in=selected_tags ) + q_all.cutoff_time = cutoff_time + #build list in this order + q_list = OrderedDict() + def extend_question_list(src, dst): + """src is a query set with questions + or an empty list + dst - is an ordered dictionary + """ + if src is None: + return #will not do anything if subscription of this type is not used + cutoff_time = src.cutoff_time + for q in src: + if q in dst: + if cutoff_time < dst[q]['cutoff_time']: + dst[q]['cutoff_time'] = cutoff_time + else: + #initialise a questions metadata dictionary to use for email reporting + dst[q] = {'cutoff_time':cutoff_time} + + extend_question_list(q_sel, q_list) + extend_question_list(q_ask, q_list) + extend_question_list(q_ans, q_list) + extend_question_list(q_all, q_list) + + ctype = ContentType.objects.get_for_model(Question) + EMAIL_UPDATE_ACTIVITY = const.TYPE_ACTIVITY_QUESTION_EMAIL_UPDATE_SENT + for q, meta_data in q_list.items(): + #todo use Activity, but first start keeping more Activity records + #act = Activity.objects.filter(content_type=ctype, object_id=q.id) + #because currently activity is not fully recorded to through + #revision records to see what kind modifications were done on + #the questions and answers + try: + update_info = Activity.objects.get(content_type=ctype, + object_id=q.id, + activity_type=EMAIL_UPDATE_ACTIVITY) + emailed_at = update_info.active_at + except Activity.DoesNotExist: + update_info = Activity(user=user, content_object=q, activity_type=EMAIL_UPDATE_ACTIVITY) + emailed_at = datetime.datetime(1970,1,1)#long time ago + except Activity.MultipleObjectsReturned: + raise Exception('server error - multiple question email activities found per user-question pair') + + q_rev = QuestionRevision.objects.filter(question=q,\ + revised_at__lt=cutoff_time,\ + revised_at__gt=emailed_at) + q_rev = q_rev.exclude(author=user) + meta_data['q_rev'] = len(q_rev) + if len(q_rev) > 0 and q.added_at == q_rev[0].revised_at: + meta_data['q_rev'] = 0 + meta_data['new_q'] = True + else: + meta_data['new_q'] = False + + new_ans = Answer.objects.filter(question=q,\ + added_at__lt=cutoff_time,\ + added_at__gt=emailed_at) + new_ans = new_ans.exclude(author=user) + meta_data['new_ans'] = len(new_ans) + ans_rev = AnswerRevision.objects.filter(answer__question=q,\ + revised_at__lt=cutoff_time,\ + revised_at__gt=emailed_at) + ans_rev = ans_rev.exclude(author=user) + meta_data['ans_rev'] = len(ans_rev) + if len(q_rev) == 0 and len(new_ans) == 0 and len(ans_rev) == 0: + meta_data['nothing_new'] = True + else: + meta_data['nothing_new'] = False + update_info.active_at = now + update_info.save() #save question email update activity + return q_list + + def __action_count(self,string,number,output): + if number > 0: + output.append(_(string) % {'num':number}) + + def send_email_alerts(self): + + #todo: move this to template + for user in User.objects.all(): + q_list = self.get_updated_questions_for_user(user) + num_q = 0 + num_moot = 0 + for meta_data in q_list.values(): + if meta_data['nothing_new'] == False: + num_q += 1 + else: + num_moot += 1 + if num_q > 0: + url_prefix = settings.APP_URL + subject = _('email update message subject') + print 'have %d updated questions for %s' % (num_q, user.username) + text = ungettext('%(name)s, this is an update message header for a question', + '%(name)s, this is an update message header for %(num)d questions',num_q) \ + % {'num':num_q, 'name':user.username} + + text += '
    ' + for q, meta_data in q_list.items(): + act_list = [] + if meta_data['nothing_new']: + continue + else: + if meta_data['new_q']: + act_list.append(_('new question')) + self.__action_count('%(num)d rev', meta_data['q_rev'],act_list) + self.__action_count('%(num)d ans', meta_data['new_ans'],act_list) + self.__action_count('%(num)d ans rev',meta_data['ans_rev'],act_list) + act_token = ', '.join(act_list) + text += '
  • %s (%s)
  • ' \ + % (url_prefix + q.get_absolute_url(), q.title, act_token) + text += '
' + if num_moot > 0: + text += '

' + text += ungettext('There is also one question which was recently '\ + +'updated but you might not have seen its latest version.', + 'There are also %(num)d more questions which were recently updated '\ + +'but you might not have seen their latest version.',num_moot) \ + % {'num':num_moot,} + text += _('Perhaps you could look up previously sent forum reminders in your mailbox.') + text += '

' + + 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]} + msg = EmailMessage(subject, text, settings.DEFAULT_FROM_EMAIL, [user.email]) + msg.content_subtype = 'html' + msg.send() -- cgit v1.2.3-1-g7c22