2 from string import lower
 
   4 from django.core.exceptions import MultipleObjectsReturned
 
   5 from django.db.models.signals import post_save
 
   7 from forum.models import Badge, Node, Action
 
   8 from forum.actions import AwardAction
 
  12 installed = dict([(b.cls, b) for b in Badge.objects.all()])
 
  14 class BadgesMeta(type):
 
  18     def __new__(mcs, name, bases, dic):
 
  19         badge = type.__new__(mcs, name, bases, dic)
 
  21         if not dic.get('abstract', False):
 
  22             if not name in installed:
 
  23                 ondb = Badge(cls=name, type=dic.get('type', Badge.BRONZE))
 
  26                 ondb = installed[name]
 
  32             def hook(action, new):
 
  33                 user = inst.award_to(action)
 
  36                     badge.award(user, action, badge.award_once)
 
  38             for action in badge.listen_to:
 
  41             BadgesMeta.by_class[name] = inst
 
  42             BadgesMeta.by_id[ondb.id] = inst
 
  46 class AbstractBadge(object):
 
  47     __metaclass__ = BadgesMeta
 
  54         raise NotImplementedError
 
  57     def description(self):
 
  58         raise NotImplementedError
 
  61     def award(cls, user, action, once=False):
 
  62         db_object = Badge.objects.get(id=cls.ondb)
 
  66                 awarded = AwardAction.get_for(user, db_object)
 
  69                 awarded = AwardAction.get_for(user, db_object, node)
 
  71             trigger = isinstance(action, Action) and action or None
 
  74                 AwardAction(user=user, node=node).save(data=dict(badge=db_object, trigger=trigger))
 
  75         except MultipleObjectsReturned:
 
  77                 logging.error('Found multiple %s badges awarded for user %s (%s)' % (self.name, user.username, user.id))
 
  79                 logging.error('Found multiple %s badges awarded for user %s (%s) and node %s' % (self.name, user.username, user.id, node.id))