summaryrefslogtreecommitdiffstats
path: root/forum/management
diff options
context:
space:
mode:
Diffstat (limited to 'forum/management')
-rw-r--r--forum/management/__init__.py0
-rw-r--r--forum/management/commands/__init__.py0
-rw-r--r--forum/management/commands/base_command.py25
-rw-r--r--forum/management/commands/clean_award_badges.py59
-rw-r--r--forum/management/commands/message_to_everyone.py12
-rw-r--r--forum/management/commands/multi_award_badges.py293
-rw-r--r--forum/management/commands/once_award_badges.py357
-rw-r--r--forum/management/commands/pg_base_command.py35
-rw-r--r--forum/management/commands/pg_clean_award_badges.py59
-rw-r--r--forum/management/commands/pg_multi_award_badges.py348
-rw-r--r--forum/management/commands/pg_once_award_badges.py350
-rw-r--r--forum/management/commands/sample_command.py7
-rw-r--r--forum/management/commands/send_email_alerts.py477
-rw-r--r--forum/management/commands/subscribe_everyone.py33
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()