from django.apps import apps
from django.db.models.signals import post_save
from django.dispatch import Signal, receiver
from notifications.signals import notify
import logging
logger = logging.getLogger(__name__)
# Signal sent during method Annotation.validate_existing_revision to update stats
revision_accepted = Signal(providing_args=['instance'])
revision_rejected = Signal(providing_args=['instance'])
revision_created = Signal(providing_args=['instance'])
def increment_stats_on_new_revision(sender, instance, **kwargs):
from iconolab.models import AnnotationRevision
if sender == AnnotationRevision:
if instance.parent_revision:
# Annotation stats
annotation = instance.annotation
annotation.stats.submitted_revisions_count += 1
if instance.state in [AnnotationRevision.ACCEPTED, AnnotationRevision.STUDIED]:
annotation.stats.accepted_revisions_count += 1
if instance.state == AnnotationRevision.ACCEPTED and instance.merge_parent_revision is not None and instance.merge_parent_revision.state == AnnotationRevision.STUDIED:
annotation.stats.awaiting_revisions_count -= 1
if instance.state in [AnnotationRevision.AWAITING]:
annotation.stats.awaiting_revisions_count += 1
annotation.stats.set_tags_stats()
annotation.stats.save()
# Image stats
image = instance.annotation.image
image.stats.submitted_revisions_count += 1
image.stats.set_tags_stats()
image.stats.save()
def increment_stats_on_new_comment(sender, instance, created, **kwargs):
from iconolab.models import IconolabComment
if created and sender == IconolabComment:
model = apps.get_model(instance.content_type.app_label,instance.content_type.model)
object_pk = instance.object_pk
annotation = model.objects.get(pk=object_pk)
annotation.stats.comments_count +=1
annotation.stats.save()
annotation.image.stats.comments_count +=1
annotation.image.stats.save()
def increment_stats_on_new_metacategory(sender, instance, created, **kwargs):
from iconolab.models import MetaCategoryInfo, MetaCategoriesCountInfo
if created and sender == MetaCategoryInfo:
metacategory = instance.metacategory
comment = instance.comment
annotation = comment.annotation
if metacategory not in annotation.stats.metacategories.all():
MetaCategoriesCountInfo.objects.create(annotation_stats_obj=annotation.stats, metacategory=metacategory, count=1)
else:
m2m_object = MetaCategoriesCountInfo.objects.get(annotation_stats_obj=annotation.stats, metacategory=metacategory)
m2m_object.count += 1
m2m_object.save()
logger.debug("NEW METACATEGORY %r on comment %r on annotation %r", metacategory, comment, annotation)
def increment_stats_on_accepted_revision(sender, instance, **kwargs):
from iconolab.models import AnnotationRevision
if sender == AnnotationRevision:
annotation = instance.annotation
annotation.stats.accepted_revisions_count += 1
annotation.stats.awaiting_revisions_count -= 1
annotation.stats.save()
def increment_stats_on_rejected_revision(sender, instance, **kwargs):
from iconolab.models import AnnotationRevision
if sender == AnnotationRevision:
annotation = instance.annotation
annotation.stats.awaiting_revisions_count -= 1
annotation.stats.save()
def increment_annotations_count(sender, instance, created, **kwargs):
from iconolab.models import Annotation
if created and sender == Annotation:
image = instance.image
image.stats.annotations_count += 1
image.stats.submitted_revisions_count += 1
image.stats.set_tags_stats()
image.stats.save()
def notify_users_on_new_comment(sender, instance, **kwargs):
from iconolab.models import IconolabComment, Annotation, MetaCategory, MetaCategoryInfo
if sender == IconolabComment and instance.content_type.app_label == 'iconolab' and instance.content_type.model == 'annotation':
comment_annotation = Annotation.objects.get(id=instance.object_pk)
# Notifying new user comment
if instance.thread_id:
notified_author = False
if instance.level > 0: # We check parent_id as django comment xtd saves comments in two steps and only set the information we need in the second step
parent_comment = IconolabComment.objects.get(id=instance.parent_id)
if parent_comment.user != instance.user:
notify.send(instance.user, recipient=parent_comment.user, verb='a répondu à votre commentaire', action_object=instance, target=comment_annotation)
if parent_comment.user == comment_annotation.author:
notified_author = True
if instance.user != comment_annotation.author and not notified_author:
notify.send(instance.user, recipient=comment_annotation.author, verb='a écrit un commentaire sur votre annotation', action_object=instance, target=comment_annotation)
def notify_users_on_metacategory(sender, instance, created, **kwargs):
from iconolab.models import MetaCategory, MetaCategoryInfo, Annotation, UserProfile
if sender == MetaCategoryInfo and created:
related_metacategory = instance.metacategory
related_comment = instance.comment
if related_comment.content_type.app_label == "iconolab" and related_comment.content_type.model == "annotation":
comment_annotation = Annotation.objects.prefetch_related("image__item__collection").get(id=related_comment.object_pk)
if related_metacategory.triggers_notifications == MetaCategory.COMMENTERS:
for commenter in comment_annotation.stats.commenters.exclude(id=related_comment.user.id).all():
notify.send(related_comment.user, recipient=commenter, verb='a fait un appel à contribution', action_object=related_comment, target=comment_annotation)
elif related_metacategory.triggers_notifications == MetaCategory.CONTRIBUTORS:
for contributor in comment_annotation.stats.contributors.exclude(id=related_comment.user.id).all():
notify.send(related_comment.user, recipient=contributor, verb='a fait un appel à contribution', action_object=related_comment, target=comment_annotation)
if related_metacategory.triggers_notifications == MetaCategory.COLLECTION_ADMINS:
for collection_admin in comment_annotation.image.item.collection.admins.all():
notify.send(related_comment.user, recipient=collection_admin.user, verb='a fait un appel à expertise', action_object=related_comment, target=comment_annotation)
def notify_users_on_new_revision(sender, instance, **kwargs):
from iconolab.models import AnnotationRevision
if sender == AnnotationRevision:
if instance.author != instance.annotation.author:
notify.send(instance.author, recipient=instance.annotation.author, verb='a proposé une révision sur votre annotation', action_object=instance, target=instance.annotation)
def notify_users_on_accepted_revision(sender, instance, **kwargs):
from iconolab.models import AnnotationRevision
if sender == AnnotationRevision:
if instance.author != instance.annotation.author and instance.state in [AnnotationRevision.ACCEPTED, AnnotationRevision.STUDIED]:
notify.send(instance.annotation.author, recipient=instance.author, verb='a étudié votre révision', action_object=instance, target=instance.annotation)
def create_user_profile(sender, instance, created, **kwargs):
from iconolab.models import UserProfile
from django.contrib.auth.models import User
if sender == User and created:
UserProfile.objects.create(user=instance)
# User profile connect
post_save.connect(create_user_profile)
# Stats handlers connect
post_save.connect(increment_annotations_count)
post_save.connect(increment_stats_on_new_comment)
post_save.connect(increment_stats_on_new_metacategory)
revision_created.connect(increment_stats_on_new_revision)
revision_accepted.connect(increment_stats_on_accepted_revision)
revision_rejected.connect(increment_stats_on_rejected_revision)
# Notifications handlers connect
post_save.connect(notify_users_on_new_comment)
post_save.connect(notify_users_on_metacategory)
revision_created.connect(notify_users_on_new_revision)
revision_accepted.connect(notify_users_on_accepted_revision)