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