]> git.openstreetmap.org Git - osqa.git/blob - forum/management/commands/send_email_alerts.py
Fix on error with decoding settings from database. Ans dome other stuff.
[osqa.git] / forum / management / commands / send_email_alerts.py
1 from datetime import datetime, timedelta
2 from django.core.management.base import NoArgsCommand
3 from django.utils.translation import ugettext as _
4 from django.template import loader, Context, Template
5 from django.core.mail import EmailMultiAlternatives
6 from django.conf import settings
7 from forum.models import KeyValue, Activity, User, QuestionSubscription
8 from forum.utils.mail import send_email
9
10 class QuestionRecord:
11     def __init__(self, question):
12         self.question = question
13         self.records = []
14
15     def log_activity(self, activity):
16         self.records.append(activity)
17
18     def get_activity_since(self, since):
19         activity = [r for r in self.records if r.active_at > since]
20         answers = [a for a in activity if a.activity_type == const.TYPE_ACTIVITY_ANSWER]
21         comments = [a for a in activity if a.activity_type in (const.TYPE_ACTIVITY_COMMENT_QUESTION, const.TYPE_ACTIVITY_COMMENT_ANSWER)]
22
23         accepted = [a for a in activity if a.activity_type == const.TYPE_ACTIVITY_MARK_ANSWER]
24
25         if len(accepted):
26             accepted = accepted[-1:][0]
27         else:
28             accepted = None
29
30         return {
31             'answers': answers,
32             'comments': comments,
33             'accepted': accepted,
34         }
35
36
37 class Command(NoArgsCommand):
38     def handle_noargs(self, **options):
39         digest_control = self.get_digest_control()
40
41         self.send_digest('daily', 'd', digest_control.value['LAST_DAILY'])
42         digest_control.value['LAST_DAILY'] = datetime.now()
43
44         if digest_control.value['LAST_WEEKLY'] + timedelta(days=7) <= datetime.now():
45             self.send_digest('weekly', 'w', digest_control.value['LAST_WEEKLY'])
46             digest_control.value['LAST_WEEKLY'] = datetime.now()
47
48         digest_control.save()
49             
50
51     def send_digest(self, name, char_in_db, control_date):
52         new_questions, question_records = self.prepare_activity(control_date)
53         new_users = User.objects.filter(date_joined__gt=control_date)
54
55         digest_subject = settings.EMAIL_SUBJECT_PREFIX + _('Daily digest')
56
57         users = User.objects.filter(subscription_settings__enable_notifications=True)
58
59         msgs = []
60
61         for u in users:
62             context = {
63                 'user': u,
64                 'digest_type': name,
65             }
66
67             if u.subscription_settings.member_joins == char_in_db:
68                 context['new_users'] = new_users
69             else:
70                 context['new_users'] = False
71
72             if u.subscription_settings.subscribed_questions == char_in_db:
73                 activity_in_subscriptions = []
74
75                 for id, r in question_records.items():
76                     try:
77                         subscription = QuestionSubscription.objects.get(question=r.question, user=u)
78
79                         record = r.get_activity_since(subscription.last_view)
80
81                         if not u.subscription_settings.notify_answers:
82                             del record['answers']
83
84                         if not u.subscription_settings.notify_comments:
85                             if u.subscription_settings.notify_comments_own_post:
86                                 record.comments = [a for a in record.comments if a.content_object.content_object.author == u]
87                                 record['own_comments_only'] = True
88                             else:
89                                 del record['comments']
90
91                         if not u.subscription_settings.notify_accepted:
92                             del record['accepted']
93
94                         if record.get('answers', False) or record.get('comments', False) or record.get('accepted', False):
95                             activity_in_subscriptions.append({'question': r.question, 'activity': record})
96                     except:
97                         pass
98
99                 context['activity_in_subscriptions'] = activity_in_subscriptions
100             else:
101                 context['activity_in_subscriptions'] = False
102
103
104             if u.subscription_settings.new_question == char_in_db:
105                 context['new_questions'] = new_questions
106                 context['watched_tags_only'] = False
107             elif u.subscription_settings.new_question_watched_tags == char_in_db:
108                 context['new_questions'] = [q for q in new_questions if
109                                             q.tags.filter(id__in=u.marked_tags.filter(user_selections__reason='good')).count() > 0]
110                 context['watched_tags_only'] = True
111             else:
112                 context['new_questions'] = False
113
114             if context['new_users'] or context['activity_in_subscriptions'] or context['new_questions']:
115                 send_email(digest_subject, (u.username, u.email), "notifications/digest.html", context, threaded=False)
116
117
118     def get_digest_control(self):
119         try:
120             digest_control = KeyValue.objects.get(key='DIGEST_CONTROL')
121         except:
122             digest_control = KeyValue(key='DIGEST_CONTROL', value={
123                 'LAST_DAILY': datetime.now() - timedelta(days=1),
124                 'LAST_WEEKLY': datetime.now() - timedelta(days=1),
125             })
126
127         return digest_control
128
129     def prepare_activity(self, since):
130         all_activity = Activity.objects.filter(active_at__gt=since, activity_type__in=(
131             const.TYPE_ACTIVITY_ASK_QUESTION, const.TYPE_ACTIVITY_ANSWER,
132             const.TYPE_ACTIVITY_COMMENT_QUESTION, const.TYPE_ACTIVITY_COMMENT_ANSWER,
133             const.TYPE_ACTIVITY_MARK_ANSWER
134         )).order_by('active_at')
135
136         question_records = {}
137         new_questions = []
138
139
140         for activity in all_activity:
141             try:
142                 question = self.get_question_for_activity(activity)
143
144                 if not question.id in question_records:
145                     question_records[question.id] = QuestionRecord(question)
146
147                 question_records[question.id].log_activity(activity)
148
149                 if activity.activity_type == const.TYPE_ACTIVITY_ASK_QUESTION:
150                     new_questions.append(question)
151             except:
152                 pass
153
154         return new_questions, question_records
155
156     def get_question_for_activity(self, activity):
157         if activity.activity_type == const.TYPE_ACTIVITY_ASK_QUESTION:
158             question = activity.content_object
159         elif activity.activity_type == const.TYPE_ACTIVITY_ANSWER:
160             question = activity.content_object.question
161         elif activity.activity_type == const.TYPE_ACTIVITY_COMMENT_QUESTION:
162             question = activity.content_object.content_object
163         elif activity.activity_type == const.TYPE_ACTIVITY_COMMENT_ANSWER:
164             question = activity.content_object.content_object.question
165         elif activity.activity_type == const.TYPE_ACTIVITY_MARK_ANSWER:
166             question = activity.content_object.question
167         else:
168             raise Exception
169
170         return question