<commit_before>import logging

from django.conf import settings
from django.contrib.auth.models import User
from django.contrib.contenttypes.models import ContentType
from django.db.models import QuerySet
from django.urls import reverse

from astrobin.models import Image
from astrobin.stories import add_story
from astrobin_apps_equipment.models import Accessory, Camera, Filter, Mount, Sensor, Software, Telescope
from astrobin_apps_iotd.models import Iotd
from astrobin_apps_notifications.services import NotificationsService
from astrobin_apps_notifications.utils import build_notification_url, push_notification
from astrobin_apps_users.services import UserService
from common.services import AppRedirectionService
from common.services.mentions_service import MentionsService
from nested_comments.models import NestedComment

log = logging.getLogger('apps')


class CommentNotificationsService:
    def __init__(self, comment):
        # type: (NestedComment) -> None
        self.comment = comment

    def send_notifications(self, force=False):
        if self.comment.pending_moderation and not force:
            return

        instance = self.comment

        model_class = instance.content_type.model_class()
        obj = instance.content_type.get_object_for_this_type(id=instance.object_id)
        object_owner = None
        notification = None
        mentions = MentionsService.get_mentions(instance.text)
        url = None

        if model_class == Image:
            object_owner = obj.user
            notification = 'new_comment'
            url = settings.BASE_URL + instance.get_absolute_url()
        elif hasattr(model_class, 'edit_proposal_by'):
            object_owner = obj.edit_proposal_by
            notification = 'new_comment_to_edit_proposal'
            url = instance.get_absolute_url()
        elif model_class == Iotd:
            object_owner = obj.judge
            notification = 'new_comment_to_scheduled_iotd'
            url = AppRedirectionService.redirect(f'/iotd/judgement-queue#comments-{obj.pk}-{instance.pk}')
        elif model_class in (
            Sensor,
            Camera,
            Telescope,
            Filter,
            Mount,
            Accessory,
            Software
        ):
            object_owner = obj.created_by
            notification = 'new_comment_to_unapproved_equipment_item'
            url = AppRedirectionService.redirect(f'/equipment/explorer/{model_class.__name__.lower()}/{obj.pk}#c{self.comment.id}')
            pass

        if UserService(object_owner).shadow_bans(instance.author):
            log.info("Skipping notification for comment because %d shadow-bans %d" % (
                object_owner.pk, instance.author.pk))
            return

        exclude = MentionsService.get_mentioned_users_with_notification_enabled(mentions, 'new_comment_mention')

        if instance.parent and \
                instance.parent.author != instance.author and \
                not instance.pending_moderation:
            recipients = [x for x in [instance.parent.author] if x not in exclude]
            if recipients:
                push_notification(
                    recipients, instance.author, 'new_comment_reply',
                    {
                        'url': build_notification_url(url, instance.author),
                        'user': instance.author.userprofile.get_display_name(),
                        'user_url': settings.BASE_URL + reverse(
                            'user_page', kwargs={'username': instance.author.username}
                        ),
                        'target': str(instance.content_object),
                        'target_url': build_notification_url(
                            settings.BASE_URL + instance.content_object.get_absolute_url(), instance.author
                        ) if hasattr(instance.content_object, 'get_absolute_url') else None,
                    }
                )

        if model_class == Image:
            if (force or not instance.pending_moderation) and not obj.is_wip:
                add_story(instance.author,
                          verb='VERB_COMMENTED_IMAGE',
                          action_object=instance,
                          target=obj)

        if object_owner and notification:
            collaborators = [object_owner] + list(obj.collaborators.all()) if hasattr(obj, 'collaborators') else [object.owner]
            if instance.author not in collaborators and \
                    (instance.parent is None or instance.parent.author != object_owner) and \
                    not instance.pending_moderation:
                recipients = [x for x in collaborators if x not in exclude]
                if recipients:
                    push_notification(
                        recipients, instance.author, notification,
                        {
                            'url': build_notification_url(url, instance.author),
                            'user': instance.author.userprofile.get_display_name(),
                            'user_url': settings.BASE_URL + reverse(
                                'user_page', kwargs={'username': instance.author.username}
                            ),
                            'target': str(self.comment.content_object),
                            'target_url': build_notification_url(
                                settings.BASE_URL + self.comment.content_object.get_absolute_url(), self.comment.author
                            ) if hasattr(self.comment.content_object, 'get_absolute_url') else None<commit_msg>(comments) Fix issue with comment notifications<commit_after>import logging

from django.conf import settings
from django.contrib.auth.models import User
from django.contrib.contenttypes.models import ContentType
from django.db.models import QuerySet
from django.urls import reverse

from astrobin.models import Image
from astrobin.stories import add_story
from astrobin_apps_equipment.models import Accessory, Camera, Filter, Mount, Sensor, Software, Telescope
from astrobin_apps_iotd.models import Iotd
from astrobin_apps_notifications.services import NotificationsService
from astrobin_apps_notifications.utils import build_notification_url, push_notification
from astrobin_apps_users.services import UserService
from common.services import AppRedirectionService
from common.services.mentions_service import MentionsService
from nested_comments.models import NestedComment

log = logging.getLogger('apps')


class CommentNotificationsService:
    def __init__(self, comment):
        # type: (NestedComment) -> None
        self.comment = comment

    def send_notifications(self, force=False):
        if self.comment.pending_moderation and not force:
            return

        instance = self.comment

        model_class = instance.content_type.model_class()
        obj = instance.content_type.get_object_for_this_type(id=instance.object_id)
        object_owner = None
        notification = None
        mentions = MentionsService.get_mentions(instance.text)
        url = None

        if model_class == Image:
            object_owner = obj.user
            notification = 'new_comment'
            url = settings.BASE_URL + instance.get_absolute_url()
        elif hasattr(model_class, 'edit_proposal_by'):
            object_owner = obj.edit_proposal_by
            notification = 'new_comment_to_edit_proposal'
            url = instance.get_absolute_url()
        elif model_class == Iotd:
            object_owner = obj.judge
            notification = 'new_comment_to_scheduled_iotd'
            url = AppRedirectionService.redirect(f'/iotd/judgement-queue#comments-{obj.pk}-{instance.pk}')
        elif model_class in (
            Sensor,
            Camera,
            Telescope,
            Filter,
            Mount,
            Accessory,
            Software
        ):
            object_owner = obj.created_by
            notification = 'new_comment_to_unapproved_equipment_item'
            url = AppRedirectionService.redirect(f'/equipment/explorer/{model_class.__name__.lower()}/{obj.pk}#c{self.comment.id}')
            pass

        if UserService(object_owner).shadow_bans(instance.author):
            log.info("Skipping notification for comment because %d shadow-bans %d" % (
                object_owner.pk, instance.author.pk))
            return

        exclude = MentionsService.get_mentioned_users_with_notification_enabled(mentions, 'new_comment_mention')

        if instance.parent and \
                instance.parent.author != instance.author and \
                not instance.pending_moderation:
            recipients = [x for x in [instance.parent.author] if x not in exclude]
            if recipients:
                push_notification(
                    recipients, instance.author, 'new_comment_reply',
                    {
                        'url': build_notification_url(url, instance.author),
                        'user': instance.author.userprofile.get_display_name(),
                        'user_url': settings.BASE_URL + reverse(
                            'user_page', kwargs={'username': instance.author.username}
                        ),
                        'target': str(instance.content_object),
                        'target_url': build_notification_url(
                            settings.BASE_URL + instance.content_object.get_absolute_url(), instance.author
                        ) if hasattr(instance.content_object, 'get_absolute_url') else None,
                    }
                )

        if model_class == Image:
            if (force or not instance.pending_moderation) and not obj.is_wip:
                add_story(instance.author,
                          verb='VERB_COMMENTED_IMAGE',
                          action_object=instance,
                          target=obj)

        if object_owner and notification:
            collaborators = [object_owner] + list(obj.collaborators.all()) if hasattr(obj, 'collaborators') else [
                object_owner]
            if instance.author not in collaborators and \
                    (instance.parent is None or instance.parent.author != object_owner) and \
                    not instance.pending_moderation:
                recipients = [x for x in collaborators if x not in exclude]
                if recipients:
                    push_notification(
                        recipients, instance.author, notification,
                        {
                            'url': build_notification_url(url, instance.author),
                            'user': instance.author.userprofile.get_display_name(),
                            'user_url': settings.BASE_URL + reverse(
                                'user_page', kwargs={'username': instance.author.username}
                            ),
                            'target': str(self.comment.content_object),
                            'target_url': build_notification_url(
                                settings.BASE_URL + self.comment.content_object.get_absolute_url(), self.comment.author
                            ) if hasattr(self.comment.content_object, 'get_absolute_url') else None
{'fraction_non_alphanumeric': 0.07485056650905522, 'fraction_numerical': 0.0, 'mean_word_length': 2.0199353448275863, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '933847', 'n_tokens_mistral': 2839, 'n_tokens_neox': 2734, 'n_words': 594}