diff options
Diffstat (limited to 'forum/management')
-rw-r--r-- | forum/management/__init__.py | 0 | ||||
-rw-r--r-- | forum/management/commands/__init__.py | 0 | ||||
-rw-r--r-- | forum/management/commands/base_command.py | 25 | ||||
-rw-r--r-- | forum/management/commands/clean_award_badges.py | 59 | ||||
-rw-r--r-- | forum/management/commands/message_to_everyone.py | 12 | ||||
-rw-r--r-- | forum/management/commands/multi_award_badges.py | 293 | ||||
-rw-r--r-- | forum/management/commands/once_award_badges.py | 357 | ||||
-rw-r--r-- | forum/management/commands/pg_base_command.py | 35 | ||||
-rw-r--r-- | forum/management/commands/pg_clean_award_badges.py | 59 | ||||
-rw-r--r-- | forum/management/commands/pg_multi_award_badges.py | 348 | ||||
-rw-r--r-- | forum/management/commands/pg_once_award_badges.py | 350 | ||||
-rw-r--r-- | forum/management/commands/sample_command.py | 7 | ||||
-rw-r--r-- | forum/management/commands/send_email_alerts.py | 477 | ||||
-rw-r--r-- | forum/management/commands/subscribe_everyone.py | 33 |
14 files changed, 0 insertions, 2055 deletions
diff --git a/forum/management/__init__.py b/forum/management/__init__.py deleted file mode 100644 index e69de29b..00000000 --- a/forum/management/__init__.py +++ /dev/null diff --git a/forum/management/commands/__init__.py b/forum/management/commands/__init__.py deleted file mode 100644 index e69de29b..00000000 --- a/forum/management/commands/__init__.py +++ /dev/null diff --git a/forum/management/commands/base_command.py b/forum/management/commands/base_command.py deleted file mode 100644 index 46a2d7a7..00000000 --- a/forum/management/commands/base_command.py +++ /dev/null @@ -1,25 +0,0 @@ -""" -#------------------------------------------------------------------------------- -# Name: Award badges command -# Purpose: This is a command file croning in background process regularly to -# query database and award badges for user's special acitivities. -# -# Author: Mike, Sailing -# -# Created: 22/01/2009 -# Copyright: (c) Mike 2009 -# Licence: GPL V2 -#------------------------------------------------------------------------------- -""" -#!/usr/bin/env python -#encoding:utf-8 - -from django.core.management.base import NoArgsCommand - -class BaseCommand(NoArgsCommand): - def update_activities_auditted(self, cursor, activity_ids): - # update processed rows to auditted - if len(activity_ids): - query = "UPDATE activity SET is_auditted = 1 WHERE id in (%s)"\ - % ','.join('%s' % item for item in activity_ids) - cursor.execute(query) diff --git a/forum/management/commands/clean_award_badges.py b/forum/management/commands/clean_award_badges.py deleted file mode 100644 index 2aab8bda..00000000 --- a/forum/management/commands/clean_award_badges.py +++ /dev/null @@ -1,59 +0,0 @@ -""" -#------------------------------------------------------------------------------- -# Name: Award badges command -# Purpose: This is a command file croning in background process regularly to -# query database and award badges for user's special acitivities. -# -# Author: Mike -# -# Created: 18/01/2009 -# Copyright: (c) Mike 2009 -# Licence: GPL V2 -#------------------------------------------------------------------------------- -""" -#!/usr/bin/env python -#encoding:utf-8 -from django.core.management.base import NoArgsCommand -from django.db import connection -from django.contrib.contenttypes.models import ContentType -from forum import models - -class Command(NoArgsCommand): - def handle_noargs(self, **options): - try: - try: - self.clean_awards() - except Exception, e: - print e - finally: - connection.close() - - def clean_awards(self): - models.Award.objects.all().delete() - - award_type =ContentType.objects.get_for_model(models.Award) - models.Activity.objects.filter(content_type=award_type).delete() - - for user in models.User.objects.all(): - user.gold = 0 - user.silver = 0 - user.bronze = 0 - user.save() - - for badge in models.Badge.objects.all(): - badge.awarded_count = 0 - badge.save() - - query = "UPDATE activity SET is_auditted = 0" - cursor = connection.cursor() - try: - cursor.execute(query) - finally: - cursor.close() - connection.close() - -def main(): - pass - -if __name__ == '__main__': - main() diff --git a/forum/management/commands/message_to_everyone.py b/forum/management/commands/message_to_everyone.py deleted file mode 100644 index c020c178..00000000 --- a/forum/management/commands/message_to_everyone.py +++ /dev/null @@ -1,12 +0,0 @@ -from django.core.management.base import NoArgsCommand -from django.contrib.auth.models import User -import sys - -class Command(NoArgsCommand): - def handle_noargs(self, **options): - msg = None - if msg == None: - print 'to run this command, please first edit the file %s' % __file__ - sys.exit(1) - for u in User.objects.all(): - u.message_set.create(message = msg % u.username) diff --git a/forum/management/commands/multi_award_badges.py b/forum/management/commands/multi_award_badges.py deleted file mode 100644 index 1ef40835..00000000 --- a/forum/management/commands/multi_award_badges.py +++ /dev/null @@ -1,293 +0,0 @@ -#encoding:utf-8 -""" -#------------------------------------------------------------------------------- -# Name: Award badges command -# Purpose: This is a command file croning in background process regularly to -# query database and award badges for user's special acitivities. -# -# Author: Mike, Sailing -# -# Created: 22/01/2009 -# Copyright: (c) Mike 2009 -# Licence: GPL V2 -#------------------------------------------------------------------------------- -""" -#!/usr/bin/env python - -from django.db import connection -from django.shortcuts import get_object_or_404 -from django.contrib.contenttypes.models import ContentType - -from forum.models import Badge, User, Award, Question, Answer, Tag -from forum import const -from forum.management.commands.base_command import BaseCommand - -class Command(BaseCommand): - def handle_noargs(self, **options): - try: - try: - self.delete_question_be_voted_up_3() - self.delete_answer_be_voted_up_3() - self.delete_question_be_vote_down_3() - self.delete_answer_be_voted_down_3() - self.answer_be_voted_up_10() - self.question_be_voted_up_10() - self.question_view_1000() - self.answer_self_question_be_voted_up_3() - self.answer_be_voted_up_100() - self.question_be_voted_up_100() - self.question_be_favorited_100() - self.question_view_10000() - self.answer_be_voted_up_25() - self.question_be_voted_up_25() - self.question_be_favorited_25() - self.question_view_2500() - self.answer_be_accepted_and_voted_up_40() - self.question_be_answered_after_60_days_and_be_voted_up_5() - self.created_tag_be_used_in_question_50() - except Exception, e: - print e - finally: - connection.close() - - def delete_question_be_voted_up_3(self): - """ - (1, '炼狱法师', 3, '炼狱法师', '删除自己有3个以上赞成票的帖子', 1, 0), - """ - query = "SELECT act.id, act.user_id, act.object_id FROM activity act, question q WHERE act.object_id = q.id AND\ - act.activity_type = %s AND\ - q.vote_up_count >=3 AND \ - act.is_auditted = 0" % (const.TYPE_ACTIVITY_DELETE_QUESTION) - self.__process_activities_badge(query, 1, Question) - - def delete_answer_be_voted_up_3(self): - """ - (1, '炼狱法师', 3, '炼狱法师', '删除自己有3个以上赞成票的帖子', 1, 0), - """ - query = "SELECT act.id, act.user_id, act.object_id FROM activity act, answer an WHERE act.object_id = an.id AND\ - act.activity_type = %s AND\ - an.vote_up_count >=3 AND \ - act.is_auditted = 0" % (const.TYPE_ACTIVITY_DELETE_ANSWER) - self.__process_activities_badge(query, 1, Answer) - - def delete_question_be_vote_down_3(self): - """ - (2, '压力白领', 3, '压力白领', '删除自己有3个以上反对票的帖子', 1, 0), - """ - query = "SELECT act.id, act.user_id, act.object_id FROM activity act, question q WHERE act.object_id = q.id AND\ - act.activity_type = %s AND\ - q.vote_down_count >=3 AND \ - act.is_auditted = 0" % (const.TYPE_ACTIVITY_DELETE_QUESTION) - content_type = ContentType.objects.get_for_model(Question) - self.__process_activities_badge(query, 2, Question) - - def delete_answer_be_voted_down_3(self): - """ - (2, '压力白领', 3, '压力白领', '删除自己有3个以上反对票的帖子', 1, 0), - """ - query = "SELECT act.id, act.user_id, act.object_id FROM activity act, answer an WHERE act.object_id = an.id AND\ - act.activity_type = %s AND\ - an.vote_down_count >=3 AND \ - act.is_auditted = 0" % (const.TYPE_ACTIVITY_DELETE_ANSWER) - self.__process_activities_badge(query, 2, Answer) - - def answer_be_voted_up_10(self): - """ - (3, '优秀回答', 3, '优秀回答', '回答好评10次以上', 1, 0), - """ - query = "SELECT act.id, act.user_id, act.object_id FROM \ - activity act, answer a WHERE act.object_id = a.id AND\ - act.activity_type = %s AND \ - a.vote_up_count >= 10 AND\ - act.is_auditted = 0" % (const.TYPE_ACTIVITY_ANSWER) - self.__process_activities_badge(query, 3, Answer) - - def question_be_voted_up_10(self): - """ - (4, '优秀问题', 3, '优秀问题', '问题好评10次以上', 1, 0), - """ - query = "SELECT act.id, act.user_id, act.object_id FROM \ - activity act, question q WHERE act.object_id = q.id AND\ - act.activity_type = %s AND \ - q.vote_up_count >= 10 AND\ - act.is_auditted = 0" % (const.TYPE_ACTIVITY_ASK_QUESTION) - self.__process_activities_badge(query, 4, Question) - - def question_view_1000(self): - """ - (6, '流行问题', 3, '流行问题', '问题的浏览量超过1000人次', 1, 0), - """ - query = "SELECT act.id, act.user_id, act.object_id FROM \ - activity act, question q WHERE act.activity_type = %s AND\ - act.object_id = q.id AND \ - q.view_count >= 1000 AND\ - act.object_id NOT IN \ - (SELECT object_id FROM award WHERE award.badge_id = %s)" \ - % (const.TYPE_ACTIVITY_ASK_QUESTION, 6) - self.__process_activities_badge(query, 6, Question, False) - - def answer_self_question_be_voted_up_3(self): - """ - (17, '自学成才', 3, '自学成才', '回答自己的问题并且有3个以上赞成票', 1, 0), - """ - query = "SELECT act.id, act.user_id, act.object_id FROM \ - activity act, answer an WHERE act.activity_type = %s AND\ - act.object_id = an.id AND\ - an.vote_up_count >= 3 AND\ - act.user_id = (SELECT user_id FROM question q WHERE q.id = an.question_id) AND\ - act.object_id NOT IN \ - (SELECT object_id FROM award WHERE award.badge_id = %s)" \ - % (const.TYPE_ACTIVITY_ANSWER, 17) - self.__process_activities_badge(query, 17, Question, False) - - def answer_be_voted_up_100(self): - """ - (18, '最有价值回答', 1, '最有价值回答', '回答超过100次赞成票', 1, 0), - """ - query = "SELECT an.id, an.author_id FROM answer an WHERE an.vote_up_count >= 100 AND an.id NOT IN \ - (SELECT object_id FROM award WHERE award.badge_id = %s)" % (18) - - self.__process_badge(query, 18, Answer) - - def question_be_voted_up_100(self): - """ - (19, '最有价值问题', 1, '最有价值问题', '问题超过100次赞成票', 1, 0), - """ - query = "SELECT q.id, q.author_id FROM question q WHERE q.vote_up_count >= 100 AND q.id NOT IN \ - (SELECT object_id FROM award WHERE award.badge_id = %s)" % (19) - - self.__process_badge(query, 19, Question) - - def question_be_favorited_100(self): - """ - (20, '万人迷', 1, '万人迷', '问题被100人以上收藏', 1, 0), - """ - query = "SELECT q.id, q.author_id FROM question q WHERE q.favourite_count >= 100 AND q.id NOT IN \ - (SELECT object_id FROM award WHERE award.badge_id = %s)" % (20) - - self.__process_badge(query, 20, Question) - - def question_view_10000(self): - """ - (21, '著名问题', 1, '著名问题', '问题的浏览量超过10000人次', 1, 0), - """ - query = "SELECT q.id, q.author_id FROM question q WHERE q.view_count >= 10000 AND q.id NOT IN \ - (SELECT object_id FROM award WHERE award.badge_id = %s)" % (21) - - self.__process_badge(query, 21, Question) - - def answer_be_voted_up_25(self): - """ - (23, '极好回答', 2, '极好回答', '回答超过25次赞成票', 1, 0), - """ - query = "SELECT a.id, a.author_id FROM answer a WHERE a.vote_up_count >= 25 AND a.id NOT IN \ - (SELECT object_id FROM award WHERE award.badge_id = %s)" % (23) - - self.__process_badge(query, 23, Answer) - - def question_be_voted_up_25(self): - """ - (24, '极好问题', 2, '极好问题', '问题超过25次赞成票', 1, 0), - """ - query = "SELECT q.id, q.author_id FROM question q WHERE q.vote_up_count >= 25 AND q.id NOT IN \ - (SELECT object_id FROM award WHERE award.badge_id = %s)" % (24) - - self.__process_badge(query, 24, Question) - - def question_be_favorited_25(self): - """ - (25, '受欢迎问题', 2, '受欢迎问题', '问题被25人以上收藏', 1, 0), - """ - query = "SELECT q.id, q.author_id FROM question q WHERE q.favourite_count >= 25 AND q.id NOT IN \ - (SELECT object_id FROM award WHERE award.badge_id = %s)" % (25) - - self.__process_badge(query, 25, Question) - - def question_view_2500(self): - """ - (31, '最受关注问题', 2, '最受关注问题', '问题的浏览量超过2500人次', 1, 0), - """ - query = "SELECT q.id, q.author_id FROM question q WHERE q.view_count >= 2500 AND q.id NOT IN \ - (SELECT object_id FROM award WHERE award.badge_id = %s)" % (31) - - self.__process_badge(query, 31, Question) - - def answer_be_accepted_and_voted_up_40(self): - """ - (34, '导师', 2, '导师', '被指定为最佳答案并且赞成票40以上', 1, 0), - """ - query = "SELECT a.id, a.author_id FROM answer a WHERE a.vote_up_count >= 40 AND\ - a.accepted = 1 AND\ - a.id NOT IN \ - (SELECT object_id FROM award WHERE award.badge_id = %s)" % (34) - - self.__process_badge(query, 34, Answer) - - def question_be_answered_after_60_days_and_be_voted_up_5(self): - """ - (35, '巫师', 2, '巫师', '在提问60天之后回答并且赞成票5次以上', 1, 0), - """ - query = "SELECT a.id, a.author_id FROM question q, answer a WHERE q.id = a.question_id AND\ - DATEDIFF(a.added_at, q.added_at) >= 60 AND\ - a.vote_up_count >= 5 AND \ - a.id NOT IN \ - (SELECT object_id FROM award WHERE award.badge_id = %s)" % (35) - - self.__process_badge(query, 35, Answer) - - def created_tag_be_used_in_question_50(self): - """ - (36, '分类专家', 2, '分类专家', '创建的标签被50个以上问题使用', 1, 0); - """ - query = "SELECT t.id, t.created_by_id FROM tag t, auth_user u WHERE t.created_by_id = u.id AND \ - t. used_count >= 50 AND \ - t.id NOT IN \ - (SELECT object_id FROM award WHERE award.badge_id = %s)" % (36) - - self.__process_badge(query, 36, Tag) - - def __process_activities_badge(self, query, badge, content_object, update_auditted=True): - content_type = ContentType.objects.get_for_model(content_object) - - cursor = connection.cursor() - try: - cursor.execute(query) - rows = cursor.fetchall() - - if update_auditted: - activity_ids = [] - badge = get_object_or_404(Badge, id=badge) - for row in rows: - activity_id = row[0] - user_id = row[1] - object_id = row[2] - - user = get_object_or_404(User, id=user_id) - award = Award(user=user, badge=badge, content_type=content_type, object_id=object_id) - award.save() - - if update_auditted: - activity_ids.append(activity_id) - - if update_auditted: - self.update_activities_auditted(cursor, activity_ids) - finally: - cursor.close() - - def __process_badge(self, query, badge, content_object): - content_type = ContentType.objects.get_for_model(Answer) - cursor = connection.cursor() - try: - cursor.execute(query) - rows = cursor.fetchall() - - badge = get_object_or_404(Badge, id=badge) - for row in rows: - object_id = row[0] - user_id = row[1] - - user = get_object_or_404(User, id=user_id) - award = Award(user=user, badge=badge, content_type=content_type, object_id=object_id) - award.save() - finally: - cursor.close() diff --git a/forum/management/commands/once_award_badges.py b/forum/management/commands/once_award_badges.py deleted file mode 100644 index ea04c11d..00000000 --- a/forum/management/commands/once_award_badges.py +++ /dev/null @@ -1,357 +0,0 @@ -#!/usr/bin/env python -#encoding:utf-8 -#------------------------------------------------------------------------------- -# Name: Award badges command -# Purpose: This is a command file croning in background process regularly to -# query database and award badges for user's special acitivities. -# -# Author: Mike, Sailing -# -# Created: 18/01/2009 -# Copyright: (c) Mike 2009 -# Licence: GPL V2 -#------------------------------------------------------------------------------- - -from datetime import datetime, date -from django.db import connection -from django.shortcuts import get_object_or_404 -from django.contrib.contenttypes.models import ContentType - -from forum.models import User, Activity, Badge, Award, Question, Answer -from forum import const -from base_command import BaseCommand -""" -(1, '炼狱法师', 3, '炼狱法师', '删除自己有3个以上赞成票的帖子', 1, 0), -(2, '压力白领', 3, '压力白领', '删除自己有3个以上反对票的帖子', 1, 0), -(3, '优秀回答', 3, '优秀回答', '回答好评10次以上', 1, 0), -(4, '优秀问题', 3, '优秀问题', '问题好评10次以上', 1, 0), -(5, '评论家', 3, '评论家', '评论10次以上', 0, 0), -(6, '流行问题', 3, '流行问题', '问题的浏览量超过1000人次', 1, 0), -(7, '巡逻兵', 3, '巡逻兵', '第一次标记垃圾帖子', 0, 0), -(8, '清洁工', 3, '清洁工', '第一次撤销投票', 0, 0), -(9, '批评家', 3, '批评家', '第一次反对票', 0, 0), -(10, '小编', 3, '小编', '第一次编辑更新', 0, 0), -(11, '村长', 3, '村长', '第一次重新标签', 0, 0), -(12, '学者', 3, '学者', '第一次标记答案', 0, 0), -(13, '学生', 3, '学生', '第一次提问并且有一次以上赞成票', 0, 0), -(14, '支持者', 3, '支持者', '第一次赞成票', 0, 0), -(15, '教师', 3, '教师', '第一次回答问题并且得到一个以上赞成票', 0, 0), -(16, '自传作者', 3, '自传作者', '完整填写用户资料所有选项', 0, 0), -(17, '自学成才', 3, '自学成才', '回答自己的问题并且有3个以上赞成票', 1, 0), -(18, '最有价值回答', 1, '最有价值回答', '回答超过100次赞成票', 1, 0), -(19, '最有价值问题', 1, '最有价值问题', '问题超过100次赞成票', 1, 0), -(20, '万人迷', 1, '万人迷', '问题被100人以上收藏', 1, 0), -(21, '著名问题', 1, '著名问题', '问题的浏览量超过10000人次', 1, 0), -(22, 'alpha用户', 2, 'alpha用户', '内测期间的活跃用户', 0, 0), -(23, '极好回答', 2, '极好回答', '回答超过25次赞成票', 1, 0), -(24, '极好问题', 2, '极好问题', '问题超过25次赞成票', 1, 0), -(25, '受欢迎问题', 2, '受欢迎问题', '问题被25人以上收藏', 1, 0), -(26, '优秀市民', 2, '优秀市民', '投票300次以上', 0, 0), -(27, '编辑主任', 2, '编辑主任', '编辑了100个帖子', 0, 0), -(28, '通才', 2, '通才', '在多个标签领域活跃', 0, 0), -(29, '专家', 2, '专家', '在一个标签领域活跃出众', 0, 0), -(30, '老鸟', 2, '老鸟', '活跃超过一年的用户', 0, 0), -(31, '最受关注问题', 2, '最受关注问题', '问题的浏览量超过2500人次', 1, 0), -(32, '学问家', 2, '学问家', '第一次回答被投赞成票10次以上', 0, 0), -(33, 'beta用户', 2, 'beta用户', 'beta期间活跃参与', 0, 0), -(34, '导师', 2, '导师', '被指定为最佳答案并且赞成票40以上', 1, 0), -(35, '巫师', 2, '巫师', '在提问60天之后回答并且赞成票5次以上', 1, 0), -(36, '分类专家', 2, '分类专家', '创建的标签被50个以上问题使用', 1, 0); - - -TYPE_ACTIVITY_ASK_QUESTION=1 -TYPE_ACTIVITY_ANSWER=2 -TYPE_ACTIVITY_COMMENT_QUESTION=3 -TYPE_ACTIVITY_COMMENT_ANSWER=4 -TYPE_ACTIVITY_UPDATE_QUESTION=5 -TYPE_ACTIVITY_UPDATE_ANSWER=6 -TYPE_ACTIVITY_PRIZE=7 -TYPE_ACTIVITY_MARK_ANSWER=8 -TYPE_ACTIVITY_VOTE_UP=9 -TYPE_ACTIVITY_VOTE_DOWN=10 -TYPE_ACTIVITY_CANCEL_VOTE=11 -TYPE_ACTIVITY_DELETE_QUESTION=12 -TYPE_ACTIVITY_DELETE_ANSWER=13 -TYPE_ACTIVITY_MARK_OFFENSIVE=14 -TYPE_ACTIVITY_UPDATE_TAGS=15 -TYPE_ACTIVITY_FAVORITE=16 -TYPE_ACTIVITY_USER_FULL_UPDATED = 17 -""" - -BADGE_AWARD_TYPE_FIRST = { - const.TYPE_ACTIVITY_MARK_OFFENSIVE : 7, - const.TYPE_ACTIVITY_CANCEL_VOTE: 8, - const.TYPE_ACTIVITY_VOTE_DOWN : 9, - const.TYPE_ACTIVITY_UPDATE_QUESTION : 10, - const.TYPE_ACTIVITY_UPDATE_ANSWER : 10, - const.TYPE_ACTIVITY_UPDATE_TAGS : 11, - const.TYPE_ACTIVITY_MARK_ANSWER : 12, - const.TYPE_ACTIVITY_VOTE_UP : 14, - const.TYPE_ACTIVITY_USER_FULL_UPDATED: 16 - -} - -class Command(BaseCommand): - def handle_noargs(self, **options): - try: - try: - self.alpha_user() - self.beta_user() - self.first_type_award() - self.first_ask_be_voted() - self.first_answer_be_voted() - self.first_answer_be_voted_10() - self.vote_count_300() - self.edit_count_100() - self.comment_count_10() - except Exception, e: - print e - finally: - connection.close() - - def alpha_user(self): - """ - Before Jan 25, 2009(Chinese New Year Eve and enter into Beta for CNProg), every registered user - will be awarded the "Alpha" badge if he has any activities. - """ - alpha_end_date = date(2009, 1, 25) - if date.today() < alpha_end_date: - badge = get_object_or_404(Badge, id=22) - for user in User.objects.all(): - award = Award.objects.filter(user=user, badge=badge) - if award and not badge.multiple: - continue - activities = Activity.objects.filter(user=user) - if len(activities) > 0: - new_award = Award(user=user, badge=badge) - new_award.save() - - def beta_user(self): - """ - Before Feb 25, 2009, every registered user - will be awarded the "Beta" badge if he has any activities. - """ - beta_end_date = date(2009, 2, 25) - if date.today() < beta_end_date: - badge = get_object_or_404(Badge, id=33) - for user in User.objects.all(): - award = Award.objects.filter(user=user, badge=badge) - if award and not badge.multiple: - continue - activities = Activity.objects.filter(user=user) - if len(activities) > 0: - new_award = Award(user=user, badge=badge) - new_award.save() - - def first_type_award(self): - - activity_types = ','.join('%s' % item for item in BADGE_AWARD_TYPE_FIRST.keys()) - # ORDER BY user_id, activity_type - query = "SELECT id, user_id, activity_type, content_type_id, object_id FROM activity WHERE is_auditted = 0 AND activity_type IN (%s) ORDER BY user_id, activity_type" % activity_types - cursor = connection.cursor() - try: - cursor.execute(query) - rows = cursor.fetchall() - # collect activity_id in current process - activity_ids = [] - last_user_id = 0 - last_activity_type = 0 - for row in rows: - activity_ids.append(row[0]) - user_id = row[1] - activity_type = row[2] - content_type_id = row[3] - object_id = row[4] - - # if the user and activity are same as the last, continue - if user_id == last_user_id and activity_type == last_activity_type: - continue; - - user = get_object_or_404(User, id=user_id) - badge = get_object_or_404(Badge, id=BADGE_AWARD_TYPE_FIRST[activity_type]) - content_type = get_object_or_404(ContentType, id=content_type_id) - - count = Award.objects.filter(user=user, badge=badge).count() - if count and not badge.multiple: - continue - else: - # new award - award = Award(user=user, badge=badge, content_type=content_type, object_id=object_id) - award.save() - - # set the current user_id and activity_type to last - last_user_id = user_id - last_activity_type = activity_type - - # update processed rows to auditted - self.update_activities_auditted(cursor, activity_ids) - finally: - cursor.close() - - def first_ask_be_voted(self): - """ - For user asked question and got first upvote, we award him following badge: - """ - query = ('SELECT act.user_id, q.vote_up_count, act.object_id FROM ' \ - + 'activity act, question q WHERE act.activity_type = %s AND ' \ - + 'act.object_id = q.id AND ' \ - + 'act.user_id NOT IN ' \ - + '(SELECT distinct user_id FROM award WHERE badge_id = %s)') \ - % (const.TYPE_ACTIVITY_ASK_QUESTION, 13) - cursor = connection.cursor() - try: - cursor.execute(query) - rows = cursor.fetchall() - - badge = get_object_or_404(Badge, id=13) - content_type = ContentType.objects.get_for_model(Question) - awarded_users = [] - for row in rows: - user_id = row[0] - vote_up_count = row[1] - object_id = row[2] - if vote_up_count > 0 and user_id not in awarded_users: - user = get_object_or_404(User, id=user_id) - award = Award(user=user, badge=badge, content_type=content_type, object_id=object_id) - award.save() - awarded_users.append(user_id) - finally: - cursor.close() - - def first_answer_be_voted(self): - """ - When user answerd questions and got first upvote, we award him following badge: - - (15, '教师', 3, '教师', '第一次回答问题并且得到一个以上赞成票', 0, 0), - """ - query = ("SELECT act.user_id, a.vote_up_count, act.object_id FROM "\ - + "activity act, answer a WHERE act.activity_type = %s AND "\ - + "act.object_id = a.id AND "\ - + "act.user_id NOT IN "\ - + "(SELECT distinct user_id FROM award WHERE badge_id = %s)") \ - % (const.TYPE_ACTIVITY_ANSWER, 15) - cursor = connection.cursor() - try: - cursor.execute(query) - rows = cursor.fetchall() - - awarded_users = [] - badge = get_object_or_404(Badge, id=15) - content_type = ContentType.objects.get_for_model(Answer) - for row in rows: - user_id = row[0] - vote_up_count = row[1] - object_id = row[2] - if vote_up_count > 0 and user_id not in awarded_users: - user = get_object_or_404(User, id=user_id) - award = Award(user=user, badge=badge, content_type=content_type, object_id=object_id) - award.save() - awarded_users.append(user_id) - finally: - cursor.close() - - def first_answer_be_voted_10(self): - """ - (32, '学问家', 2, '学问家', '第一次回答被投赞成票10次以上', 0, 0) - """ - query = ("SELECT act.user_id, act.object_id FROM " \ - + "activity act, answer a WHERE act.object_id = a.id AND "\ - + "act.activity_type = %s AND "\ - + "a.vote_up_count >= 10 AND "\ - + "act.user_id NOT IN "\ - + "(SELECT user_id FROM award WHERE badge_id = %s)") \ - % (const.TYPE_ACTIVITY_ANSWER, 32) - cursor = connection.cursor() - try: - cursor.execute(query) - rows = cursor.fetchall() - - awarded_users = [] - badge = get_object_or_404(Badge, id=32) - content_type = ContentType.objects.get_for_model(Answer) - for row in rows: - user_id = row[0] - if user_id not in awarded_users: - user = get_object_or_404(User, id=user_id) - object_id = row[1] - award = Award(user=user, badge=badge, content_type=content_type, object_id=object_id) - award.save() - awarded_users.append(user_id) - finally: - cursor.close() - - def vote_count_300(self): - """ - (26, '优秀市民', 2, '优秀市民', '投票300次以上', 0, 0) - """ - query = ("SELECT count(*) vote_count, user_id FROM activity WHERE " \ - + "activity_type = %s OR " \ - + "activity_type = %s AND " \ - + "user_id NOT IN (SELECT user_id FROM award WHERE badge_id = %s) " \ - + "GROUP BY user_id HAVING vote_count >= 300") \ - % ( - const.TYPE_ACTIVITY_VOTE_UP, - const.TYPE_ACTIVITY_VOTE_DOWN, - 2 - ) - - self.__award_for_count_num(query, 26) - - def edit_count_100(self): - """ - (27, '编辑主任', 2, '编辑主任', '编辑了100个帖子', 0, 0) - """ - query = ("SELECT count(*) vote_count, user_id FROM activity WHERE " \ - + "activity_type = %s OR " \ - + "activity_type = %s AND " \ - + "user_id NOT IN (SELECT user_id FROM award WHERE badge_id = %s) " \ - + "GROUP BY user_id HAVING vote_count >= 100" )\ - % ( - const.TYPE_ACTIVITY_UPDATE_QUESTION, - const.TYPE_ACTIVITY_UPDATE_ANSWER, - 27 - ) - - self.__award_for_count_num(query, 27) - - def comment_count_10(self): - """ - (5, '评论家', 3, '评论家', '评论10次以上', 0, 0), - """ - query = ("SELECT count(*) vote_count, user_id FROM activity WHERE " \ - + "activity_type = %s OR " \ - + "activity_type = %s AND " \ - + "user_id NOT IN (SELECT user_id FROM award WHERE badge_id = %s) " \ - + "GROUP BY user_id HAVING vote_count >= 10" )\ - % ( - const.TYPE_ACTIVITY_COMMENT_QUESTION, - const.TYPE_ACTIVITY_COMMENT_ANSWER, - 5 - ) - self.__award_for_count_num(query, 5) - - def __award_for_count_num(self, query, badge): - cursor = connection.cursor() - try: - cursor.execute(query) - rows = cursor.fetchall() - - awarded_users = [] - badge = get_object_or_404(Badge, id=badge) - for row in rows: - vote_count = row[0] - user_id = row[1] - - if user_id not in awarded_users: - user = get_object_or_404(User, id=user_id) - award = Award(user=user, badge=badge)#todo: will this work with content_object null? - award.save() - awarded_users.append(user_id) - finally: - cursor.close() - -def main(): - pass - -if __name__ == '__main__': - main() diff --git a/forum/management/commands/pg_base_command.py b/forum/management/commands/pg_base_command.py deleted file mode 100644 index b3167dcf..00000000 --- a/forum/management/commands/pg_base_command.py +++ /dev/null @@ -1,35 +0,0 @@ -#!/usr/bin/env python -#encoding:utf-8 -#------------------------------------------------------------------------------- -# Name: Award badges command -# Purpose: This is a command file croning in background process regularly to -# query database and award badges for user's special acitivities. -# -# Author: Mike, Sailing -# -# Created: 22/01/2009 -# Copyright: (c) Mike 2009 -# Licence: GPL V2 -#------------------------------------------------------------------------------- - -from datetime import datetime, date -from django.core.management.base import NoArgsCommand -from django.db import connection -from django.shortcuts import get_object_or_404 -from django.contrib.contenttypes.models import ContentType - -from forum.models import * -from forum.const import * - -class BaseCommand(NoArgsCommand): - def update_activities_auditted(self, cursor, activity_ids): - # update processed rows to auditted - if len(activity_ids): - query = "UPDATE activity SET is_auditted = TRUE WHERE id in (%s)"\ - % ','.join('%s' % item for item in activity_ids) - cursor.execute(query) - - - - - diff --git a/forum/management/commands/pg_clean_award_badges.py b/forum/management/commands/pg_clean_award_badges.py deleted file mode 100644 index b3925a68..00000000 --- a/forum/management/commands/pg_clean_award_badges.py +++ /dev/null @@ -1,59 +0,0 @@ -#------------------------------------------------------------------------------- -# Name: Award badges command -# Purpose: This is a command file croning in background process regularly to -# query database and award badges for user's special acitivities. -# -# Author: Mike -# -# Created: 18/01/2009 -# Copyright: (c) Mike 2009 -# Licence: GPL V2 -#------------------------------------------------------------------------------- -#!/usr/bin/env python -#encoding:utf-8 -from django.core.management.base import NoArgsCommand -from django.db import connection -from django.shortcuts import get_object_or_404 -from django.contrib.contenttypes.models import ContentType - -from forum.models import * - -class Command(NoArgsCommand): - def handle_noargs(self, **options): - try: - try: - self.clean_awards() - except Exception, e: - print e - finally: - connection.close() - - def clean_awards(self): - Award.objects.all().delete() - - award_type =ContentType.objects.get_for_model(Award) - Activity.objects.filter(content_type=award_type).delete() - - for user in User.objects.all(): - user.gold = 0 - user.silver = 0 - user.bronze = 0 - user.save() - - for badge in Badge.objects.all(): - badge.awarded_count = 0 - badge.save() - - query = "UPDATE activity SET is_auditted = FALSE" - cursor = connection.cursor() - try: - cursor.execute(query) - finally: - cursor.close() - connection.close() - -def main(): - pass - -if __name__ == '__main__': - main()
\ No newline at end of file diff --git a/forum/management/commands/pg_multi_award_badges.py b/forum/management/commands/pg_multi_award_badges.py deleted file mode 100644 index 75f84bfe..00000000 --- a/forum/management/commands/pg_multi_award_badges.py +++ /dev/null @@ -1,348 +0,0 @@ -#!/usr/bin/env python -#encoding:utf-8 -#------------------------------------------------------------------------------- -# Name: Award badges command -# Purpose: This is a command file croning in background process regularly to -# query database and award badges for user's special acitivities. -# -# Author: Mike, Sailing -# -# Created: 22/01/2009 -# Copyright: (c) Mike 2009 -# Licence: GPL V2 -#------------------------------------------------------------------------------- - -from datetime import datetime, date -from django.core.management.base import NoArgsCommand -from django.db import connection -from django.shortcuts import get_object_or_404 -from django.contrib.contenttypes.models import ContentType - -from forum.models import * -from forum.const import * -from pg_base_command import BaseCommand -""" -(1, '????', 3, '????', '?????3?????????', 1, 0), -(2, '????', 3, '????', '?????3?????????', 1, 0), -(3, '????', 3, '????', '????10???', 1, 0), -(4, '????', 3, '????', '????10???', 1, 0), -(5, '???', 3, '???', '??10???', 0, 0), -(6, '????', 3, '????', '????????1000??', 1, 0), -(7, '???', 3, '???', '?????????', 0, 0), -(8, '???', 3, '???', '???????', 0, 0), -(9, '???', 3, '???', '??????', 0, 0), -(10, '??', 3, '??', '???????', 0, 0), -(11, '??', 3, '??', '???????', 0, 0), -(12, '??', 3, '??', '???????', 0, 0), -(13, '??', 3, '??', '???????????????', 0, 0), -(14, '???', 3, '???', '??????', 0, 0), -(15, '??', 3, '??', '??????????????????', 0, 0), -(16, '????', 3, '????', '????????????', 0, 0), -(17, '????', 3, '????', '??????????3??????', 1, 0), -(18, '??????', 1, '??????', '????100????', 1, 0), -(19, '??????', 1, '??????', '????100????', 1, 0), -(20, '???', 1, '???', '???100?????', 1, 0), -(21, '????', 1, '????', '????????10000??', 1, 0), -(22, 'alpha??', 2, 'alpha??', '?????????', 0, 0), -(23, '????', 2, '????', '????25????', 1, 0), -(24, '????', 2, '????', '????25????', 1, 0), -(25, '?????', 2, '?????', '???25?????', 1, 0), -(26, '????', 2, '????', '??300???', 0, 0), -(27, '????', 2, '????', '???100???', 0, 0), -(28, '??', 2, '??', '?????????', 0, 0), -(29, '??', 2, '??', '???????????', 0, 0), -(30, '??', 2, '??', '?????????', 0, 0), -(31, '??????', 2, '??????', '????????2500??', 1, 0), -(32, '???', 2, '???', '??????????10???', 0, 0), -(33, 'beta??', 2, 'beta??', 'beta??????', 0, 0), -(34, '??', 2, '??', '?????????????40??', 1, 0), -(35, '??', 2, '??', '???60??????????5???', 1, 0), -(36, '????', 2, '????', '??????50???????', 1, 0); - - -TYPE_ACTIVITY_ASK_QUESTION=1 -TYPE_ACTIVITY_ANSWER=2 -TYPE_ACTIVITY_COMMENT_QUESTION=3 -TYPE_ACTIVITY_COMMENT_ANSWER=4 -TYPE_ACTIVITY_UPDATE_QUESTION=5 -TYPE_ACTIVITY_UPDATE_ANSWER=6 -TYPE_ACTIVITY_PRIZE=7 -TYPE_ACTIVITY_MARK_ANSWER=8 -TYPE_ACTIVITY_VOTE_UP=9 -TYPE_ACTIVITY_VOTE_DOWN=10 -TYPE_ACTIVITY_CANCEL_VOTE=11 -TYPE_ACTIVITY_DELETE_QUESTION=12 -TYPE_ACTIVITY_DELETE_ANSWER=13 -TYPE_ACTIVITY_MARK_OFFENSIVE=14 -TYPE_ACTIVITY_UPDATE_TAGS=15 -TYPE_ACTIVITY_FAVORITE=16 -TYPE_ACTIVITY_USER_FULL_UPDATED = 17 -""" - -class Command(BaseCommand): - def handle_noargs(self, **options): - try: - try: - self.delete_question_be_voted_up_3() - self.delete_answer_be_voted_up_3() - self.delete_question_be_vote_down_3() - self.delete_answer_be_voted_down_3() - self.answer_be_voted_up_10() - self.question_be_voted_up_10() - self.question_view_1000() - self.answer_self_question_be_voted_up_3() - self.answer_be_voted_up_100() - self.question_be_voted_up_100() - self.question_be_favorited_100() - self.question_view_10000() - self.answer_be_voted_up_25() - self.question_be_voted_up_25() - self.question_be_favorited_25() - self.question_view_2500() - self.answer_be_accepted_and_voted_up_40() - self.question_be_answered_after_60_days_and_be_voted_up_5() - self.created_tag_be_used_in_question_50() - except Exception, e: - print e - finally: - connection.close() - - def delete_question_be_voted_up_3(self): - """ - (1, '????', 3, '????', '?????3?????????', 1, 0), - """ - query = "SELECT act.id, act.user_id, act.object_id FROM activity act, question q WHERE act.object_id = q.id AND\ - act.activity_type = %s AND\ - q.vote_up_count >=3 AND \ - not act.is_auditted" % (TYPE_ACTIVITY_DELETE_QUESTION) - self.__process_activities_badge(query, 1, Question) - - def delete_answer_be_voted_up_3(self): - """ - (1, '????', 3, '????', '?????3?????????', 1, 0), - """ - query = "SELECT act.id, act.user_id, act.object_id FROM activity act, answer an WHERE act.object_id = an.id AND\ - act.activity_type = %s AND\ - an.vote_up_count >=3 AND \ - not act.is_auditted" % (TYPE_ACTIVITY_DELETE_ANSWER) - self.__process_activities_badge(query, 1, Answer) - - def delete_question_be_vote_down_3(self): - """ - (2, '????', 3, '????', '?????3?????????', 1, 0), - """ - query = "SELECT act.id, act.user_id, act.object_id FROM activity act, question q WHERE act.object_id = q.id AND\ - act.activity_type = %s AND\ - q.vote_down_count >=3 AND \ - not act.is_auditted" % (TYPE_ACTIVITY_DELETE_QUESTION) - content_type = ContentType.objects.get_for_model(Question) - self.__process_activities_badge(query, 2, Question) - - def delete_answer_be_voted_down_3(self): - """ - (2, '????', 3, '????', '?????3?????????', 1, 0), - """ - query = "SELECT act.id, act.user_id, act.object_id FROM activity act, answer an WHERE act.object_id = an.id AND\ - act.activity_type = %s AND\ - an.vote_down_count >=3 AND \ - not act.is_auditted" % (TYPE_ACTIVITY_DELETE_ANSWER) - self.__process_activities_badge(query, 2, Answer) - - def answer_be_voted_up_10(self): - """ - (3, '????', 3, '????', '????10???', 1, 0), - """ - query = "SELECT act.id, act.user_id, act.object_id FROM \ - activity act, answer a WHERE act.object_id = a.id AND\ - act.activity_type = %s AND \ - a.vote_up_count >= 10 AND\ - not act.is_auditted" % (TYPE_ACTIVITY_ANSWER) - self.__process_activities_badge(query, 3, Answer) - - def question_be_voted_up_10(self): - """ - (4, '????', 3, '????', '????10???', 1, 0), - """ - query = "SELECT act.id, act.user_id, act.object_id FROM \ - activity act, question q WHERE act.object_id = q.id AND\ - act.activity_type = %s AND \ - q.vote_up_count >= 10 AND\ - not act.is_auditted" % (TYPE_ACTIVITY_ASK_QUESTION) - self.__process_activities_badge(query, 4, Question) - - def question_view_1000(self): - """ - (6, '????', 3, '????', '????????1000??', 1, 0), - """ - query = "SELECT act.id, act.user_id, act.object_id FROM \ - activity act, question q WHERE act.activity_type = %s AND\ - act.object_id = q.id AND \ - q.view_count >= 1000 AND\ - act.object_id NOT IN \ - (SELECT object_id FROM award WHERE award.badge_id = %s)" % (TYPE_ACTIVITY_ASK_QUESTION, 6) - self.__process_activities_badge(query, 6, Question, False) - - def answer_self_question_be_voted_up_3(self): - """ - (17, '????', 3, '????', '??????????3??????', 1, 0), - """ - query = "SELECT act.id, act.user_id, act.object_id FROM \ - activity act, answer an WHERE act.activity_type = %s AND\ - act.object_id = an.id AND\ - an.vote_up_count >= 3 AND\ - act.user_id = (SELECT user_id FROM question q WHERE q.id = an.question_id) AND\ - act.object_id NOT IN \ - (SELECT object_id FROM award WHERE award.badge_id = %s)" % (TYPE_ACTIVITY_ANSWER, 17) - self.__process_activities_badge(query, 17, Question, False) - - def answer_be_voted_up_100(self): - """ - (18, '??????', 1, '??????', '????100????', 1, 0), - """ - query = "SELECT an.id, an.author_id FROM answer an WHERE an.vote_up_count >= 100 AND an.id NOT IN \ - (SELECT object_id FROM award WHERE award.badge_id = %s)" % (18) - - self.__process_badge(query, 18, Answer) - - def question_be_voted_up_100(self): - """ - (19, '??????', 1, '??????', '????100????', 1, 0), - """ - query = "SELECT q.id, q.author_id FROM question q WHERE q.vote_up_count >= 100 AND q.id NOT IN \ - (SELECT object_id FROM award WHERE award.badge_id = %s)" % (19) - - self.__process_badge(query, 19, Question) - - def question_be_favorited_100(self): - """ - (20, '???', 1, '???', '???100?????', 1, 0), - """ - query = "SELECT q.id, q.author_id FROM question q WHERE q.favourite_count >= 100 AND q.id NOT IN \ - (SELECT object_id FROM award WHERE award.badge_id = %s)" % (20) - - self.__process_badge(query, 20, Question) - - def question_view_10000(self): - """ - (21, '????', 1, '????', '????????10000??', 1, 0), - """ - query = "SELECT q.id, q.author_id FROM question q WHERE q.view_count >= 10000 AND q.id NOT IN \ - (SELECT object_id FROM award WHERE award.badge_id = %s)" % (21) - - self.__process_badge(query, 21, Question) - - def answer_be_voted_up_25(self): - """ - (23, '????', 2, '????', '????25????', 1, 0), - """ - query = "SELECT a.id, a.author_id FROM answer a WHERE a.vote_up_count >= 25 AND a.id NOT IN \ - (SELECT object_id FROM award WHERE award.badge_id = %s)" % (23) - - self.__process_badge(query, 23, Answer) - - def question_be_voted_up_25(self): - """ - (24, '????', 2, '????', '????25????', 1, 0), - """ - query = "SELECT q.id, q.author_id FROM question q WHERE q.vote_up_count >= 25 AND q.id NOT IN \ - (SELECT object_id FROM award WHERE award.badge_id = %s)" % (24) - - self.__process_badge(query, 24, Question) - - def question_be_favorited_25(self): - """ - (25, '?????', 2, '?????', '???25?????', 1, 0), - """ - query = "SELECT q.id, q.author_id FROM question q WHERE q.favourite_count >= 25 AND q.id NOT IN \ - (SELECT object_id FROM award WHERE award.badge_id = %s)" % (25) - - self.__process_badge(query, 25, Question) - - def question_view_2500(self): - """ - (31, '??????', 2, '??????', '????????2500??', 1, 0), - """ - query = "SELECT q.id, q.author_id FROM question q WHERE q.view_count >= 2500 AND q.id NOT IN \ - (SELECT object_id FROM award WHERE award.badge_id = %s)" % (31) - - self.__process_badge(query, 31, Question) - - def answer_be_accepted_and_voted_up_40(self): - """ - (34, '??', 2, '??', '?????????????40??', 1, 0), - """ - query = "SELECT a.id, a.author_id FROM answer a WHERE a.vote_up_count >= 40 AND\ - a.accepted AND\ - a.id NOT IN \ - (SELECT object_id FROM award WHERE award.badge_id = %s)" % (34) - - self.__process_badge(query, 34, Answer) - - def question_be_answered_after_60_days_and_be_voted_up_5(self): - """ - (35, '??', 2, '??', '???60??????????5???', 1, 0), - """ - query = "SELECT a.id, a.author_id FROM question q, answer a WHERE q.id = a.question_id AND\ - (a.added_at + '60 day'::INTERVAL) >= q.added_at AND\ - a.vote_up_count >= 5 AND \ - a.id NOT IN \ - (SELECT object_id FROM award WHERE award.badge_id = %s)" % (35) - - self.__process_badge(query, 35, Answer) - - def created_tag_be_used_in_question_50(self): - """ - (36, '????', 2, '????', '??????50???????', 1, 0); - """ - query = "SELECT t.id, t.created_by_id FROM tag t, auth_user u WHERE t.created_by_id = u.id AND \ - t. used_count >= 50 AND \ - t.id NOT IN \ - (SELECT object_id FROM award WHERE award.badge_id = %s)" % (36) - - self.__process_badge(query, 36, Tag) - - def __process_activities_badge(self, query, badge, content_object, update_auditted=True): - content_type = ContentType.objects.get_for_model(content_object) - - cursor = connection.cursor() - try: - cursor.execute(query) - rows = cursor.fetchall() - - if update_auditted: - activity_ids = [] - badge = get_object_or_404(Badge, id=badge) - for row in rows: - activity_id = row[0] - user_id = row[1] - object_id = row[2] - - user = get_object_or_404(User, id=user_id) - award = Award(user=user, badge=badge, content_type=content_type, object_id=object_id) - award.save() - - if update_auditted: - activity_ids.append(activity_id) - - if update_auditted: - self.update_activities_auditted(cursor, activity_ids) - finally: - cursor.close() - - def __process_badge(self, query, badge, content_object): - content_type = ContentType.objects.get_for_model(Answer) - cursor = connection.cursor() - try: - cursor.execute(query) - rows = cursor.fetchall() - - badge = get_object_or_404(Badge, id=badge) - for row in rows: - object_id = row[0] - user_id = row[1] - - user = get_object_or_404(User, id=user_id) - award = Award(user=user, badge=badge, content_type=content_type, object_id=object_id) - award.save() - finally: - cursor.close() diff --git a/forum/management/commands/pg_once_award_badges.py b/forum/management/commands/pg_once_award_badges.py deleted file mode 100644 index b2f79363..00000000 --- a/forum/management/commands/pg_once_award_badges.py +++ /dev/null @@ -1,350 +0,0 @@ -#!/usr/bin/env python -#encoding:utf-8 -#------------------------------------------------------------------------------- -# Name: Award badges command -# Purpose: This is a command file croning in background process regularly to -# query database and award badges for user's special acitivities. -# -# Author: Mike, Sailing -# -# Created: 18/01/2009 -# Copyright: (c) Mike 2009 -# Licence: GPL V2 -#------------------------------------------------------------------------------- - -from datetime import datetime, date -from django.db import connection -from django.shortcuts import get_object_or_404 -from django.contrib.contenttypes.models import ContentType - -from forum.models import * -from forum.const import * -from pg_base_command import BaseCommand -""" -(1, '????', 3, '????', '?????3?????????', 1, 0), -(2, '????', 3, '????', '?????3?????????', 1, 0), -(3, '????', 3, '????', '????10???', 1, 0), -(4, '????', 3, '????', '????10???', 1, 0), -(5, '???', 3, '???', '??10???', 0, 0), -(6, '????', 3, '????', '????????1000??', 1, 0), -(7, '???', 3, '???', '?????????', 0, 0), -(8, '???', 3, '???', '???????', 0, 0), -(9, '???', 3, '???', '??????', 0, 0), -(10, '??', 3, '??', '???????', 0, 0), -(11, '??', 3, '??', '???????', 0, 0), -(12, '??', 3, '??', '???????', 0, 0), -(13, '??', 3, '??', '???????????????', 0, 0), -(14, '???', 3, '???', '??????', 0, 0), -(15, '??', 3, '??', '??????????????????', 0, 0), -(16, '????', 3, '????', '????????????', 0, 0), -(17, '????', 3, '????', '??????????3??????', 1, 0), -(18, '??????', 1, '??????', '????100????', 1, 0), -(19, '??????', 1, '??????', '????100????', 1, 0), -(20, '???', 1, '???', '???100?????', 1, 0), -(21, '????', 1, '????', '????????10000??', 1, 0), -(22, 'alpha??', 2, 'alpha??', '?????????', 0, 0), -(23, '????', 2, '????', '????25????', 1, 0), -(24, '????', 2, '????', '????25????', 1, 0), -(25, '?????', 2, '?????', '???25?????', 1, 0), -(26, '????', 2, '????', '??300???', 0, 0), -(27, '????', 2, '????', '???100???', 0, 0), -(28, '??', 2, '??', '?????????', 0, 0), -(29, '??', 2, '??', '???????????', 0, 0), -(30, '??', 2, '??', '?????????', 0, 0), -(31, '??????', 2, '??????', '????????2500??', 1, 0), -(32, '???', 2, '???', '??????????10???', 0, 0), -(33, 'beta??', 2, 'beta??', 'beta??????', 0, 0), -(34, '??', 2, '??', '?????????????40??', 1, 0), -(35, '??', 2, '??', '???60??????????5???', 1, 0), -(36, '????', 2, '????', '??????50???????', 1, 0); - - -TYPE_ACTIVITY_ASK_QUESTION=1 -TYPE_ACTIVITY_ANSWER=2 -TYPE_ACTIVITY_COMMENT_QUESTION=3 -TYPE_ACTIVITY_COMMENT_ANSWER=4 -TYPE_ACTIVITY_UPDATE_QUESTION=5 -TYPE_ACTIVITY_UPDATE_ANSWER=6 -TYPE_ACTIVITY_PRIZE=7 -TYPE_ACTIVITY_MARK_ANSWER=8 -TYPE_ACTIVITY_VOTE_UP=9 -TYPE_ACTIVITY_VOTE_DOWN=10 -TYPE_ACTIVITY_CANCEL_VOTE=11 -TYPE_ACTIVITY_DELETE_QUESTION=12 -TYPE_ACTIVITY_DELETE_ANSWER=13 -TYPE_ACTIVITY_MARK_OFFENSIVE=14 -TYPE_ACTIVITY_UPDATE_TAGS=15 -TYPE_ACTIVITY_FAVORITE=16 -TYPE_ACTIVITY_USER_FULL_UPDATED = 17 -""" - -BADGE_AWARD_TYPE_FIRST = { - TYPE_ACTIVITY_MARK_OFFENSIVE : 7, - TYPE_ACTIVITY_CANCEL_VOTE: 8, - TYPE_ACTIVITY_VOTE_DOWN : 9, - TYPE_ACTIVITY_UPDATE_QUESTION : 10, - TYPE_ACTIVITY_UPDATE_ANSWER : 10, - TYPE_ACTIVITY_UPDATE_TAGS : 11, - TYPE_ACTIVITY_MARK_ANSWER : 12, - TYPE_ACTIVITY_VOTE_UP : 14, - TYPE_ACTIVITY_USER_FULL_UPDATED: 16 - -} - -class Command(BaseCommand): - def handle_noargs(self, **options): - try: - try: - self.alpha_user() - self.beta_user() - self.first_type_award() - self.first_ask_be_voted() - self.first_answer_be_voted() - self.first_answer_be_voted_10() - self.vote_count_300() - self.edit_count_100() - self.comment_count_10() - except Exception, e: - print e - finally: - connection.close() - - def alpha_user(self): - """ - Before Jan 25, 2009(Chinese New Year Eve and enter into Beta for CNProg), every registered user - will be awarded the "Alpha" badge if he has any activities. - """ - alpha_end_date = date(2009, 1, 25) - if date.today() < alpha_end_date: - badge = get_object_or_404(Badge, id=22) - for user in User.objects.all(): - award = Award.objects.filter(user=user, badge=badge) - if award and not badge.multiple: - continue - activities = Activity.objects.filter(user=user) - if len(activities) > 0: - new_award = Award(user=user, badge=badge) - new_award.save() - - def beta_user(self): - """ - Before Feb 25, 2009, every registered user - will be awarded the "Beta" badge if he has any activities. - """ - beta_end_date = date(2009, 2, 25) - if date.today() < beta_end_date: - badge = get_object_or_404(Badge, id=33) - for user in User.objects.all(): - award = Award.objects.filter(user=user, badge=badge) - if award and not badge.multiple: - continue - activities = Activity.objects.filter(user=user) - if len(activities) > 0: - new_award = Award(user=user, badge=badge) - new_award.save() - - def first_type_award(self): - """ - This will award below badges for users first behaviors: - - (7, '???', 3, '???', '?????????', 0, 0), - (8, '???', 3, '???', '???????', 0, 0), - (9, '???', 3, '???', '??????', 0, 0), - (10, '??', 3, '??', '???????', 0, 0), - (11, '??', 3, '??', '???????', 0, 0), - (12, '??', 3, '??', '???????', 0, 0), - (14, '???', 3, '???', '??????', 0, 0), - (16, '????', 3, '????', '????????????', 0, 0), - """ - activity_types = ','.join('%s' % item for item in BADGE_AWARD_TYPE_FIRST.keys()) - # ORDER BY user_id, activity_type - query = "SELECT id, user_id, activity_type, content_type_id, object_id FROM activity WHERE not is_auditted AND activity_type IN (%s) ORDER BY user_id, activity_type" % activity_types - - cursor = connection.cursor() - try: - cursor.execute(query) - rows = cursor.fetchall() - # collect activity_id in current process - activity_ids = [] - last_user_id = 0 - last_activity_type = 0 - for row in rows: - activity_ids.append(row[0]) - user_id = row[1] - activity_type = row[2] - content_type_id = row[3] - object_id = row[4] - - # if the user and activity are same as the last, continue - if user_id == last_user_id and activity_type == last_activity_type: - continue; - - user = get_object_or_404(User, id=user_id) - badge = get_object_or_404(Badge, id=BADGE_AWARD_TYPE_FIRST[activity_type]) - content_type = get_object_or_404(ContentType, id=content_type_id) - - count = Award.objects.filter(user=user, badge=badge).count() - if count and not badge.multiple: - continue - else: - # new award - award = Award(user=user, badge=badge, content_type=content_type, object_id=object_id) - award.save() - - # set the current user_id and activity_type to last - last_user_id = user_id - last_activity_type = activity_type - - # update processed rows to auditted - self.update_activities_auditted(cursor, activity_ids) - finally: - cursor.close() - - def first_ask_be_voted(self): - """ - For user asked question and got first upvote, we award him following badge: - - (13, '??', 3, '??', '???????????????', 0, 0), - """ - query = "SELECT act.user_id, q.vote_up_count, act.object_id FROM " \ - "activity act, question q WHERE act.activity_type = %s AND " \ - "act.object_id = q.id AND " \ - "act.user_id NOT IN (SELECT distinct user_id FROM award WHERE badge_id = %s)" % (TYPE_ACTIVITY_ASK_QUESTION, 13) - cursor = connection.cursor() - try: - cursor.execute(query) - rows = cursor.fetchall() - - badge = get_object_or_404(Badge, id=13) - content_type = ContentType.objects.get_for_model(Question) - awarded_users = [] - for row in rows: - user_id = row[0] - vote_up_count = row[1] - object_id = row[2] - if vote_up_count > 0 and user_id not in awarded_users: - user = get_object_or_404(User, id=user_id) - award = Award(user=user, badge=badge, content_type=content_type, object_id=object_id) - award.save() - awarded_users.append(user_id) - finally: - cursor.close() - - def first_answer_be_voted(self): - """ - When user answerd questions and got first upvote, we award him following badge: - - (15, '??', 3, '??', '??????????????????', 0, 0), - """ - query = "SELECT act.user_id, a.vote_up_count, act.object_id FROM " \ - "activity act, answer a WHERE act.activity_type = %s AND " \ - "act.object_id = a.id AND " \ - "act.user_id NOT IN (SELECT distinct user_id FROM award WHERE badge_id = %s)" % (TYPE_ACTIVITY_ANSWER, 15) - cursor = connection.cursor() - try: - cursor.execute(query) - rows = cursor.fetchall() - - awarded_users = [] - badge = get_object_or_404(Badge, id=15) - content_type = ContentType.objects.get_for_model(Answer) - for row in rows: - user_id = row[0] - vote_up_count = row[1] - object_id = row[2] - if vote_up_count > 0 and user_id not in awarded_users: - user = get_object_or_404(User, id=user_id) - award = Award(user=user, badge=badge, content_type=content_type, object_id=object_id) - award.save() - awarded_users.append(user_id) - finally: - cursor.close() - - def first_answer_be_voted_10(self): - """ - (32, '???', 2, '???', '??????????10???', 0, 0) - """ - query = "SELECT act.user_id, act.object_id FROM " \ - "activity act, answer a WHERE act.object_id = a.id AND " \ - "act.activity_type = %s AND " \ - "a.vote_up_count >= 10 AND " \ - "act.user_id NOT IN (SELECT user_id FROM award WHERE badge_id = %s)" % (TYPE_ACTIVITY_ANSWER, 32) - cursor = connection.cursor() - try: - cursor.execute(query) - rows = cursor.fetchall() - - awarded_users = [] - badge = get_object_or_404(Badge, id=32) - content_type = ContentType.objects.get_for_model(Answer) - for row in rows: - user_id = row[0] - if user_id not in awarded_users: - user = get_object_or_404(User, id=user_id) - object_id = row[1] - award = Award(user=user, badge=badge, content_type=content_type, object_id=object_id) - award.save() - awarded_users.append(user_id) - finally: - cursor.close() - - def vote_count_300(self): - """ - (26, '????', 2, '????', '??300???', 0, 0) - """ - query = "SELECT count(*) as vote_count, user_id FROM activity WHERE " \ - "activity_type = %s OR " \ - "activity_type = %s AND " \ - "user_id NOT IN (SELECT user_id FROM award WHERE badge_id = %s) " \ - "GROUP BY user_id HAVING count(*) >= 300" % (TYPE_ACTIVITY_VOTE_UP, TYPE_ACTIVITY_VOTE_DOWN, 26) - - self.__award_for_count_num(query, 26) - - def edit_count_100(self): - """ - (27, '????', 2, '????', '???100???', 0, 0) - """ - query = "SELECT count(*) as vote_count, user_id FROM activity WHERE " \ - "activity_type = %s OR " \ - "activity_type = %s AND " \ - "user_id NOT IN (SELECT user_id FROM award WHERE badge_id = %s) " \ - "GROUP BY user_id HAVING count(*) >= 100" % (TYPE_ACTIVITY_UPDATE_QUESTION, TYPE_ACTIVITY_UPDATE_ANSWER, 27) - - self.__award_for_count_num(query, 27) - - def comment_count_10(self): - """ - (5, '???', 3, '???', '??10???', 0, 0), - """ - query = "SELECT count(*) as vote_count, user_id FROM activity WHERE " \ - "activity_type = %s OR " \ - "activity_type = %s AND " \ - "user_id NOT IN (SELECT user_id FROM award WHERE badge_id = %s) " \ - "GROUP BY user_id HAVING count(*) >= 10" % (TYPE_ACTIVITY_COMMENT_QUESTION, TYPE_ACTIVITY_COMMENT_ANSWER, 5) - self.__award_for_count_num(query, 5) - - def __award_for_count_num(self, query, badge): - cursor = connection.cursor() - try: - cursor.execute(query) - rows = cursor.fetchall() - - awarded_users = [] - badge = get_object_or_404(Badge, id=badge) - for row in rows: - vote_count = row[0] - user_id = row[1] - - if user_id not in awarded_users: - user = get_object_or_404(User, id=user_id) - award = Award(user=user, badge=badge) - award.save() - awarded_users.append(user_id) - finally: - cursor.close() - -def main(): - pass - -if __name__ == '__main__': - main() diff --git a/forum/management/commands/sample_command.py b/forum/management/commands/sample_command.py deleted file mode 100644 index 55e67235..00000000 --- a/forum/management/commands/sample_command.py +++ /dev/null @@ -1,7 +0,0 @@ -from django.core.management.base import NoArgsCommand -from forum.models import Comment - -class Command(NoArgsCommand): - def handle_noargs(self, **options): - objs = Comment.objects.all() - print objs
\ No newline at end of file diff --git a/forum/management/commands/send_email_alerts.py b/forum/management/commands/send_email_alerts.py deleted file mode 100644 index 2c39311f..00000000 --- a/forum/management/commands/send_email_alerts.py +++ /dev/null @@ -1,477 +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 User, Question, Answer, Tag, QuestionRevision -from forum.models import AnswerRevision, Activity, EmailFeedSetting -from forum.models import Comment -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 -from forum.conf import settings as forum_settings -from django.utils.datastructures import SortedDict -from django.contrib.contenttypes.models import ContentType -from forum import const - -DEBUG_THIS_COMMAND = False - -def get_all_origin_posts(mentions): - origin_posts = set() - for mention in mentions: - post = mention.content_object - origin_posts.add(post.get_origin_post()) - return list(origin_posts) - -#todo: refactor this as class -def extend_question_list(src, dst, limit=False, add_mention=False): - """src is a query set with questions - or None - dst - is an ordered dictionary - update reporting cutoff time for each question - to the latest value to be more permissive about updates - """ - if src is None:#is not QuerySet - return #will not do anything if subscription of this type is not used - if limit and len(dst.keys()) >= forum_settings.MAX_ALERTS_PER_EMAIL: - return - cutoff_time = src.cutoff_time#todo: this limits use of function to query sets - #but sometimes we have a list on the input (like in the case of comment) - for q in src: - if q in dst: - meta_data = dst[q] - else: - meta_data = {'cutoff_time': cutoff_time} - dst[q] = meta_data - - if cutoff_time > meta_data['cutoff_time']: - #the latest cutoff time wins for a given question - #if the question falls into several subscription groups - #this makes mailer more eager in sending email - meta_data['cutoff_time'] = cutoff_time - if add_mention: - if 'mentions' in meta_data: - meta_data['mentions'] += 1 - else: - meta_data['mentions'] = 1 - -def format_action_count(string, number, output): - if number > 0: - output.append(_(string) % {'num':number}) - -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): - """ - retreive relevant question updates for the user - according to their subscriptions and recorded question - views - """ - - user_feeds = EmailFeedSetting.objects.filter(subscriber=user).exclude(frequency='n') - - should_proceed = False - for feed in user_feeds: - if feed.should_send_now() == True: - should_proceed = True - break - - #shortcirquit - if there is no ripe feed to work on for this user - if should_proceed == False: - return {} - - #these are placeholders for separate query sets per question group - #there are four groups - one for each EmailFeedSetting.feed_type - #and each group has subtypes A and B - #that's because of the strange thing commented below - #see note on Q and F objects marked with todo tag - q_sel_A = None - q_sel_B = None - - q_ask_A = None - q_ask_B = None - - q_ans_A = None - q_ans_B = None - - q_all_A = None - q_all_B = None - - q_m_and_c_A = None#mentions and post comments - q_m_and_c_B = None - - #base question query set for this user - #basic things - not deleted, not closed, not too old - #not last edited by the same user - base_qs = Question.objects.exclude( - last_activity_by=user - ).exclude( - last_activity_at__lt=user.date_joined#exclude old stuff - ).exclude( - deleted=True - ).exclude( - closed=True - ).order_by('-last_activity_at') - #todo: for some reason filter on did not work as expected ~Q(viewed__who=user) | - # Q(viewed__who=user,viewed__when__lt=F('last_activity_at')) - #returns way more questions than you might think it should - #so because of that I've created separate query sets Q_set2 and Q_set3 - #plus two separate queries run faster! - - #build two two queries based - - #questions that are not seen by the user at all - not_seen_qs = base_qs.filter(~Q(viewed__who=user)) - #questions that were seen, but before last modification - seen_before_last_mod_qs = base_qs.filter( - Q( - viewed__who=user, - viewed__when__lt=F('last_activity_at') - ) - ) - - for feed in user_feeds: - #each group of updates represented by the corresponding - #query set has it's own cutoff time - #that cutoff time is computed for each user individually - #and stored as a parameter "cutoff_time" - # - #we won't send email for a given question if an email has been - #sent after that cutoff_time - if feed.should_send_now(): - - if DEBUG_THIS_COMMAND == False: - feed.mark_reported_now() - cutoff_time = feed.get_previous_report_cutoff_time() - - #shorten variables for convenience - Q_set_A = not_seen_qs - Q_set_B = seen_before_last_mod_qs - - if feed.feed_type == 'q_sel': - q_sel_A = Q_set_A.filter(followed_by=user) - q_sel_A.cutoff_time = cutoff_time #store cutoff time per query set - q_sel_B = Q_set_B.filter(followed_by=user) - q_sel_B.cutoff_time = cutoff_time #store cutoff time per query set - - elif feed.feed_type == 'q_ask': - q_ask_A = Q_set_A.filter(author=user) - q_ask_A.cutoff_time = cutoff_time - q_ask_B = Q_set_B.filter(author=user) - q_ask_B.cutoff_time = cutoff_time - - elif feed.feed_type == 'q_ans': - q_ans_A = Q_set_A.filter(answers__author=user) - q_ans_A = q_ans_A[:forum_settings.MAX_ALERTS_PER_EMAIL] - q_ans_A.cutoff_time = cutoff_time - - q_ans_B = Q_set_B.filter(answers__author=user) - q_ans_B = q_ans_B[:forum_settings.MAX_ALERTS_PER_EMAIL] - q_ans_B.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_A = Q_set_A.exclude( tags__in=ignored_tags ) - - q_all_B = Q_set_B.exclude( tags__in=ignored_tags ) - else: - selected_tags = Tag.objects.filter( - user_selections__reason='good', - user_selections__user=user - ) - q_all_A = Q_set_A.filter( tags__in=selected_tags ) - q_all_B = Q_set_B.filter( tags__in=selected_tags ) - - q_all_A = q_all_A[:forum_settings.MAX_ALERTS_PER_EMAIL] - q_all_B = q_all_B[:forum_settings.MAX_ALERTS_PER_EMAIL] - q_all_A.cutoff_time = cutoff_time - q_all_B.cutoff_time = cutoff_time - - #build ordered list questions for the email report - q_list = SortedDict() - - #todo: refactor q_list into a separate class - extend_question_list(q_sel_A, q_list) - extend_question_list(q_sel_B, q_list) - - #build list of comment and mention responses here - #it is separate because posts are not marked as changed - #when people add comments - #mention responses could be collected in the loop above, but - #it is inconvenient, because feed_type m_and_c bundles the two - #also we collect metadata for these here - if user_feeds.exists(feed_type='m_and_c'): - feed = user_feeds.get(feed_type='m_and_c') - if feed.should_report_now(): - cutoff_time = feed.get_previous_report_cutoff_time() - comments = Comment.objects.filter( - added_at__gt = cutoff_time, - user__ne = user, - ) - q_commented = list() - for c in comments: - post = c.content_object - if post.author != user: - continue - - #skip is post was seen by the user after - #the comment posting time - - if isinstance(post, Question): - q_commented.append(post) - elif isinstance(post, Answer): - q_commented.append(post.question) - - for q in q_commented: - if q in q_list: - meta_data = q_list[q] - if meta_data['cutoff_time'] < cutoff_time: - meta_data['cutoff_time'] = cutoff_time - if 'comments' in meta_data: - meta_data['comments'] += 1 - else: - meta_data['comments'] = 1 - - mentions = Activity.objects.get_mentions( - mentioned_at__gt = cutoff_time, - mentioned_whom = user - ) - - mention_posts = get_all_origin_posts(mentions) - q_mentions_id = [q.id for q in mention_posts] - - q_mentions_A = Q_set_A.filter(id__in = q_mentions_id) - q_mentions_A.cutoff_time = cutoff_time - extend_question_list(q_mentions_A, q_list, add_mention=True) - - q_mentions_B = Q_set_B.filter(id__in = q_mentions_id) - q_mentions_B.cutoff_time = cutoff_time - extend_question_list(q_mentions_B, q_list, add_mention=True) - - if user.tag_filter_setting == 'interesting': - extend_question_list(q_all_A, q_list) - extend_question_list(q_all_B, q_list) - - extend_question_list(q_ask_A, q_list, limit=True) - extend_question_list(q_ask_B, q_list, limit=True) - - extend_question_list(q_ans_A, q_list, limit=True) - extend_question_list(q_ans_B, q_list, limit=True) - - if user.tag_filter_setting == 'ignored': - extend_question_list(q_all_A, q_list, limit=True) - extend_question_list(q_all_B, q_list, limit=True) - - ctype = ContentType.objects.get_for_model(Question) - EMAIL_UPDATE_ACTIVITY = const.TYPE_ACTIVITY_EMAIL_UPDATE_SENT - - #up to this point we still don't know if emails about - #collected questions were sent recently - #the next loop examines activity record and decides - #for each question, whether it needs to be included or not - #into the report - - for q, meta_data in q_list.items(): - #this loop edits meta_data for each question - #so that user will receive counts on new edits new answers, etc - #and marks questions that need to be skipped - #because an email about them was sent recently enough - - #also it keeps a record of latest email activity per question per user - try: - #todo: is it possible to use content_object here, instead of - #content type and object_id pair? - update_info = Activity.objects.get( - user=user, - 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' - ) - - cutoff_time = meta_data['cutoff_time']#cutoff time for the question - - #skip question if we need to wait longer because - #the delay before the next email has not yet elapsed - #or if last email was sent after the most recent modification - if emailed_at > cutoff_time or emailed_at > q.last_activity_at: - meta_data['skip'] = True - continue - - #collect info on all sorts of news that happened after - #the most recent emailing to the user about this question - q_rev = QuestionRevision.objects.filter( - question=q, - revised_at__gt=emailed_at - ) - - q_rev = q_rev.exclude(author=user) - - #now update all sorts of metadata per question - 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__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__gt=emailed_at - ) - ans_rev = ans_rev.exclude(author=user) - meta_data['ans_rev'] = len(ans_rev) - - #finally skip question if there are no news indeed - if len(q_rev) + len(new_ans) + len(ans_rev) == 0: - meta_data['skip'] = True - else: - meta_data['skip'] = False - update_info.active_at = datetime.datetime.now() - if DEBUG_THIS_COMMAND == False: - update_info.save() #save question email update activity - #q_list is actually an ordered dictionary - #print 'user %s gets %d' % (user.username, len(q_list.keys())) - #todo: sort question list by update time - return q_list - - def send_email_alerts(self): - #does not change the database, only sends the email - #todo: move this to template - for user in User.objects.all(): - #todo: q_list is a dictionary, not a list - q_list = self.get_updated_questions_for_user(user) - if len(q_list.keys()) == 0: - continue - num_q = 0 - num_moot = 0 - for meta_data in q_list.values(): - if meta_data['skip']: - num_moot = True - else: - num_q += 1 - if num_q > 0: - url_prefix = forum_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 %(num)d question', - '%(name)s, this is an update message header for %(num)d questions',num_q) \ - % {'num':num_q, 'name':user.username} - - text += '<ul>' - items_added = 0 - items_unreported = 0 - for q, meta_data in q_list.items(): - act_list = [] - if meta_data['skip']: - continue - if items_added >= forum_settings.MAX_ALERTS_PER_EMAIL: - items_unreported = num_q - items_added #may be inaccurate actually, but it's ok - - else: - items_added += 1 - if meta_data['new_q']: - act_list.append(_('new question')) - format_action_count('%(num)d rev', meta_data['q_rev'],act_list) - format_action_count('%(num)d ans', meta_data['new_ans'],act_list) - format_action_count('%(num)d ans rev',meta_data['ans_rev'],act_list) - act_token = ', '.join(act_list) - text += '<li><a href="%s?sort=latest">%s</a> <font color="#777777">(%s)</font></li>' \ - % (url_prefix + q.get_absolute_url(), q.title, act_token) - text += '</ul>' - text += '<p></p>' - #if len(q_list.keys()) >= forum_settings.MAX_ALERTS_PER_EMAIL: - # text += _('There may be more questions updated since ' - # 'you have logged in last time as this list is ' - # 'abridged for your convinience. Please visit ' - # 'the forum and see what\'s new!<br>' - # ) - - text += _( - 'Please visit the forum and see what\'s new! ' - 'Could you spread the word about it - ' - 'can somebody you know help answering those questions or ' - 'benefit from posting one?' - ) - - feeds = EmailFeedSetting.objects.filter( - subscriber=user, - ) - feed_freq = [feed.frequency for feed in feeds] - text += '<p></p>' - if 'd' in feed_freq: - text += _('Your most frequent subscription setting is \'daily\' ' - 'on selected questions. If you are receiving more than one ' - 'email per day' - 'please tell about this issue to the forum administrator.' - ) - elif 'w' in feed_freq: - text += _('Your most frequent subscription setting is \'weekly\' ' - 'if you are receiving this email more than once a week ' - 'please report this issue to the forum administrator.' - ) - text += ' ' - text += _( - 'There is a chance that you may be receiving links seen ' - 'before - due to a technicality that will eventually go away. ' - ) - # text += '</p>' - #if num_moot > 0: - # text += '<p></p>' - # 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 += '</p>' - - link = url_prefix + user.get_profile_url() + '?sort=email_subscriptions' - 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' - msg.send() - else: - msg2 = EmailMessage( - subject, - text, - settings.DEFAULT_FROM_EMAIL, - ['your@email.com'] - ) - msg2.content_subtype = 'html' - msg2.send() diff --git a/forum/management/commands/subscribe_everyone.py b/forum/management/commands/subscribe_everyone.py deleted file mode 100644 index fac4168f..00000000 --- a/forum/management/commands/subscribe_everyone.py +++ /dev/null @@ -1,33 +0,0 @@ -from django.core.management.base import NoArgsCommand -from django.db import connection -from forum.models import EmailFeedSetting, User -from django.core.mail import EmailMessage - -class Command(NoArgsCommand): - def handle_noargs(self, **options): - try: - try: - self.subscribe_everyone() - except Exception, e: - print e - finally: - connection.close() - - def subscribe_everyone(self): - - feed_type_info = EmailFeedSetting.FEED_TYPES - for user in User.objects.all(): - for feed_type in feed_type_info: - try: - feed_setting = EmailFeedSetting.objects.get( - subscriber=user, - feed_type = feed_type[0] - ) - except EmailFeedSetting.DoesNotExist: - feed_setting = EmailFeedSetting( - subscriber=user, - feed_type=feed_type[0] - ) - feed_setting.frequency = 'w' - feed_setting.reported_at = None - feed_setting.save() |