1 from django.utils.translation import ugettext as _
2 from django.db.models import F
3 from forum.models.action import ActionProxy, DummyActionProxy
4 from forum.models import Vote, Flag
5 from forum import settings
7 class VoteAction(ActionProxy):
8 def update_node_score(self, inc):
9 self.node.score = F('score') + inc
12 def process_vote_action(self, value):
13 self.update_node_score(value)
14 vote = Vote(node=self.node, user=self.user, action=self, value=value)
17 def cancel_action(self):
19 self.update_node_score(-vote.value)
23 def get_for(cls, user, node):
25 vote = Vote.objects.get(user=user, node=node)
31 def get_action_for(cls, user, node):
33 vote = Vote.objects.get(user=user, node=node)
38 def describe_vote(self, vote_desc, viewer=None):
39 return _("%(user)s %(vote_desc)s %(post_desc)s") % {
40 'user': self.hyperlink(self.user.get_profile_url(), self.friendly_username(viewer, self.user)),
41 'vote_desc': vote_desc, 'post_desc': self.describe_node(viewer, self.node)
45 class VoteUpAction(VoteAction):
46 def repute_users(self):
47 self.repute(self.node.author, int(settings.REP_GAIN_BY_UPVOTED))
49 def process_action(self):
50 self.process_vote_action(1)
51 self.user.reset_vote_up_count_cache()
53 def cancel_action(self):
54 super(VoteUpAction, self).cancel_action()
55 self.user.reset_vote_up_count_cache()
57 def describe(self, viewer=None):
58 return self.describe_vote(_("voted up"), viewer)
60 class VoteDownAction(VoteAction):
61 def repute_users(self):
62 self.repute(self.node.author, -int(settings.REP_LOST_BY_DOWNVOTED))
63 self.repute(self.user, -int(settings.REP_LOST_BY_DOWNVOTING))
65 def process_action(self):
66 self.process_vote_action(-1)
67 self.user.reset_vote_down_count_cache()
69 def cancel_action(self):
70 super(VoteDownAction, self).cancel_action()
71 self.user.reset_vote_down_count_cache()
73 def describe(self, viewer=None):
74 return self.describe_vote(_("voted down"), viewer)
77 class VoteUpCommentAction(VoteUpAction):
78 def repute_users(self):
81 def process_action(self):
82 self.process_vote_action(1)
84 def cancel_action(self):
85 super(VoteUpAction, self).cancel_action()
87 def describe(self, viewer=None):
88 return self.describe_vote(_("liked"), viewer)
91 class FlagAction(ActionProxy):
92 def repute_users(self):
93 self.repute(self.node.author, -int(settings.REP_LOST_BY_FLAGGED))
95 def process_action(self):
96 flag = Flag(user=self.user, node=self.node, action=self, reason=self.extra)
98 self.node.reset_flag_count_cache()
100 if self.node.flag_count >= int(settings.FLAG_COUNT_TO_HIDE_POST):
101 self.repute(self.node.author, -int(settings.REP_LOST_BY_FLAGGED_3_TIMES))
103 if self.node.flag_count >= int(settings.FLAG_COUNT_TO_DELETE_POST):
104 self.repute(self.node.author, -int(settings.REP_LOST_BY_FLAGGED_5_TIMES))
105 if not self.node.nis.deleted:
106 DeleteAction(node=self.node, user=self.user, extra="BYFLAGGED").save()
108 def cancel_action(self):
110 self.node.reset_flag_count_cache()
113 def get_for(cls, user, node):
115 flag = Flag.objects.get(user=user, node=node)
116 return flag.reason or _("No reason given")
120 def describe(self, viewer=None):
121 return _("%(user)s flagged %(post_desc)s: %(reason)s") % {
122 'user': self.hyperlink(self.user.get_profile_url(), self.friendly_username(viewer, self.user)),
123 'post_desc': self.describe_node(viewer, self.node), 'reason': self.extra
127 class AcceptAnswerAction(ActionProxy):
128 def repute_users(self):
129 if (self.user == self.node.parent.author) and (not self.user == self.node.author):
130 self.repute(self.user, int(settings.REP_GAIN_BY_ACCEPTING))
132 if self.user != self.node.author:
133 self.repute(self.node.author, int(settings.REP_GAIN_BY_ACCEPTED))
135 def process_action(self):
136 self.node.marked = True
137 self.node.nstate.accepted = self
139 self.node.question.reset_accepted_count_cache()
141 def cancel_action(self):
142 self.node.marked = False
143 self.node.nstate.accepted = None
145 self.node.question.reset_accepted_count_cache()
147 def describe(self, viewer=None):
149 question = answer.parent
151 if self.user == question.author:
152 asker = (self.user == viewer) and _("your") or _("his")
154 asker = self.hyperlink(question.author.get_profile_url(), question.author.username)
156 return _("%(user)s accepted %(answerer)s answer on %(asker)s question %(question)s") % {
157 'user': self.hyperlink(self.user.get_profile_url(), self.friendly_username(viewer, self.user)),
158 'answerer': self.hyperlink(answer.author.get_profile_url(), self.friendly_ownername(viewer, answer.author)),
160 'question': self.hyperlink(question.get_absolute_url(), question.title)
164 class FavoriteAction(ActionProxy):
165 def process_action(self):
166 self.node.reset_favorite_count_cache()
168 def cancel_action(self):
169 self.process_action()
171 def describe(self, viewer=None):
172 return _("%(user)s marked %(post_desc)s as favorite") % {
173 'user': self.hyperlink(self.user.get_profile_url(), self.friendly_username(viewer, self.user)),
174 'post_desc': self.describe_node(viewer, self.node),
178 class DeleteAction(ActionProxy):
179 def process_action(self):
180 self.node.mark_deleted(self)
182 if self.node.node_type == "answer":
183 self.node.question.reset_answer_count_cache()
185 def cancel_action(self):
186 self.node.mark_deleted(None)
188 if self.node.node_type == "answer":
189 self.node.question.reset_answer_count_cache()
191 def describe(self, viewer=None):
192 return _("%(user)s deleted %(post_desc)s") % {
193 'user': self.hyperlink(self.user.get_profile_url(), self.friendly_username(viewer, self.user)),
194 'post_desc': self.describe_node(viewer, self.node)
198 if self.extra != "BYFLAGGED":
201 return _("flagged by multiple users: ") + "; ".join([f.extra for f in FlagAction.objects.filter(node=self.node)])
203 class UnknownAction(ActionProxy):
207 class QuestionViewAction(DummyActionProxy):
208 def __init__(self, node, user, ip=None):
211 super(QuestionViewAction, self).__init__(ip)
213 def process_action(self):
214 self.node.extra_count = F('extra_count') + 1