def test_get_mentions_two_mentions_multiline(self): text = "Hello [url=https://www.astrobin.com/users/foo/]@Foo Smith[/url]\nHello " \ "[url=https://www.astrobin.com/users/bar/]@Bar Test[/url]" mentions = MentionsService.get_mentions(text) self.assertTrue("foo" in mentions) self.assertTrue("bar" in mentions)
def test_get_mentions_no_www(self): text = "Hello [url=https://astrobin.com/users/foo/]@Foo Bar[/url]" self.assertEqual(["foo"], MentionsService.get_mentions(text))
def test_get_mentions_localhost_and_port(self): text = "Hello [url=http://localhost:8084/users/foo/]@Foo Bar[/url]" self.assertEqual(["foo"], MentionsService.get_mentions(text))
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}') 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} ), } ) 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: if instance.author != object_owner and \ (instance.parent is None or instance.parent.author != object_owner) and \ not instance.pending_moderation: recipients = [x for x in [object_owner] 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} ), } )
def test_get_mentions_no_mentions(self): self.assertEqual([], MentionsService.get_mentions("hello"))
def image_post_save(sender, instance, created, **kwargs): # type: (object, Image, bool, object) -> None if created: instance.user.userprofile.premium_counter += 1 instance.user.userprofile.save(keep_deleted=True) if not instance.is_wip: if not instance.skip_notifications: push_notification_for_new_image.apply_async(args=( instance.user.pk, instance.pk, )) if instance.moderator_decision == 1: add_story(instance.user, verb='VERB_UPLOADED_IMAGE', action_object=instance) if Image.all_objects.filter(user=instance.user).count() == 1: push_notification( [instance.user], None, 'congratulations_for_your_first_image', { 'BASE_URL': settings.BASE_URL, 'PREMIUM_MAX_IMAGES_FREE': settings.PREMIUM_MAX_IMAGES_FREE, 'url': reverse_url('image_detail', args=(instance.get_id(), )) }) mentions = MentionsService.get_mentions(instance.description_bbcode) else: mentions = cache.get("image.%d.image_pre_save_mentions" % instance.pk, []) for username in mentions: user = get_object_or_None(User, username=username) if not user: try: profile = get_object_or_None(UserProfile, real_name=username) if profile: user = profile.user except MultipleObjectsReturned: user = None if user and user != instance.user: thumb = instance.thumbnail_raw('gallery', None, sync=True) push_notification( [user], instance.user, 'new_image_description_mention', { 'image': instance, 'image_thumbnail': thumb.url if thumb else None, 'url': build_notification_url( settings.BASE_URL + instance.get_absolute_url(), instance.user), 'user': instance.user.userprofile.get_display_name(), 'user_url': settings.BASE_URL + reverse_url( 'user_page', kwargs={'username': instance.user}), }) if not instance.uploader_in_progress: groups = instance.user.joined_group_set.filter(autosubmission=True) for group in groups: if instance.is_wip: group.images.remove(instance) else: group.images.add(instance) if instance.user.userprofile.updated < datetime.datetime.now( ) - datetime.timedelta(minutes=5): instance.user.save() try: instance.user.userprofile.save(keep_deleted=True) except UserProfile.DoesNotExist: pass UserService(instance.user).clear_gallery_image_list_cache() if instance.user.userprofile.auto_submit_to_iotd_tp_process: IotdService.submit_to_iotd_tp_process(instance.user, instance, False)
def forum_post_post_save(sender, instance, created, **kwargs): def notify_subscribers(mentions): # type: (List[str]) -> None recipients = list( instance.topic.subscribers.exclude(pk__in=list( set([instance.user.pk] + [ x.pk for x in MentionsService. get_mentioned_users_with_notification_enabled( mentions, 'new_forum_post_mention') ])))) if recipients: push_notification( recipients, instance.user, 'new_forum_reply', { 'user': instance.user.userprofile.get_display_name(), 'user_url': settings.BASE_URL + reverse_url( 'user_page', kwargs={'username': instance.user}), 'post_url': build_notification_url( settings.BASE_URL + instance.get_absolute_url(), instance.user), 'topic_url': build_notification_url( settings.BASE_URL + instance.topic.get_absolute_url(), instance.user), 'topic_name': instance.topic.name, 'unsubscribe_url': build_notification_url( settings.BASE_URL + reverse_url('pybb:delete_subscription', args=[instance.topic.id]), instance.user) }) def notify_mentioned(mentions): # type: (List[str]) -> None for username in mentions: user = get_object_or_None(User, username=username) if user is None: try: profile = get_object_or_None(UserProfile, real_name=username) if profile: user = profile.user except MultipleObjectsReturned: user = None if user: push_notification( [user], instance.user, 'new_forum_post_mention', { 'url': build_notification_url( settings.BASE_URL + instance.get_absolute_url(), instance.user), 'user': instance.user.userprofile.get_display_name(), 'user_url': settings.BASE_URL + reverse_url( 'user_page', kwargs={'username': instance.user}), 'post': instance.topic.name, }) if created: if hasattr(instance.topic.forum, 'group'): instance.topic.forum.group.save() # trigger date_updated update if get_pybb_profile(instance.user).autosubscribe and \ perms.may_subscribe_topic(instance.user, instance.topic): instance.topic.subscribers.add(instance.user) mentions = MentionsService.get_mentions(instance.body) if not instance.on_moderation: notify_subscribers(mentions) notify_mentioned(mentions) else: NotificationsService.email_superusers( 'New forum post needs moderation', '%s%s' % (settings.BASE_URL, instance.get_absolute_url())) else: mentions = cache.get( "post.%d.forum_post_pre_save_mentions" % instance.pk, []) cache.delete("post.%d.forum_post_pre_save_mentions" % instance.pk) if cache.get("post.%d.forum_post_pre_save_approved" % instance.pk): push_notification( [instance.user], None, 'forum_post_approved', { 'url': build_notification_url(settings.BASE_URL + instance.get_absolute_url()) }) notify_subscribers(mentions) notify_mentioned(mentions) cache.delete("post.%d.forum_post_pre_save_approved" % instance.pk) cache_key = make_template_fragment_key( 'home_page_latest_from_forums', (instance.user.pk, instance.user.userprofile.language)) cache.delete(cache_key)
def nested_comment_post_save(sender, instance, created, **kwargs): if created: model_class = instance.content_type.model_class() obj = instance.content_type.get_object_for_this_type( id=instance.object_id) url = settings.BASE_URL + instance.get_absolute_url() mentions = MentionsService.get_mentions(instance.text) if model_class == Image: image = instance.content_type.get_object_for_this_type( id=instance.object_id) if image.is_wip: return if UserService(obj.user).shadow_bans(instance.author): log.info( "Skipping notification for comment because %d shadow-bans %d" % (obj.user.pk, instance.author.pk)) return if instance.author != obj.user: push_notification( [obj.user], 'new_comment', { 'url': url, 'user': instance.author.userprofile.get_display_name(), 'user_url': settings.BASE_URL + reverse_url( 'user_page', kwargs={'username': instance.author.username}), }) if instance.parent and instance.parent.author != instance.author: push_notification( [instance.parent.author], 'new_comment_reply', { 'url': url, 'user': instance.author.userprofile.get_display_name(), 'user_url': settings.BASE_URL + reverse_url( 'user_page', kwargs={'username': instance.author.username}), }) add_story(instance.author, verb='VERB_COMMENTED_IMAGE', action_object=instance, target=obj) elif model_class == Gear: if not instance.parent: gear, gear_type = get_correct_gear(obj.id) user_attr_lookup = { 'Telescope': 'telescopes', 'Camera': 'cameras', 'Mount': 'mounts', 'FocalReducer': 'focal_reducers', 'Software': 'software', 'Filter': 'filters', 'Accessory': 'accessories', } recipients = [ x.user for x in UserProfile.objects.filter( **{user_attr_lookup[gear_type]: gear}) ] notification = 'new_gear_discussion' else: notification = 'new_comment_reply' recipients = [instance.parent.author] push_notification( recipients, notification, { 'url': url, 'user': instance.author.userprofile.get_display_name(), 'user_url': settings.BASE_URL + reverse_url('user_page', kwargs={'username': instance.author.username}), }) add_story(instance.author, verb='VERB_COMMENTED_GEAR', action_object=instance, target=gear) if hasattr(instance.content_object, "updated"): # This will trigger the auto_now fields in the content_object # We do it only if created, because the content_object needs to # only be updated if the number of comments changes. instance.content_object.save(keep_deleted=True) else: mentions = cache.get( "user.%d.comment_pre_save_mentions" % instance.author.pk, []) for username in mentions: try: user = User.objects.get(username=username) push_notification( [user], 'new_comment_mention', { 'url': settings.BASE_URL + instance.get_absolute_url(), 'user': instance.author.userprofile.get_display_name(), 'user_url': settings.BASE_URL + reverse_url( 'user_page', kwargs={'username': instance.author}), }) except User.DoesNotExist: pass
def test_get_mentions_empty_string(self): self.assertEquals([], MentionsService.get_mentions(""))
def test_get_mentions_unique_mentions(self): text = "Hello [url=https://www.astrobin.com/users/foo/]@Foo Smith[/url] and [url=https://www.astrobin.com/users/foo/]@Foo Smith[/url]" self.assertEquals(["foo"], MentionsService.get_mentions(text))
def test_get_mentions_two_mentions_multiline(self): text = "Hello [url=https://www.astrobin.com/users/foo/]@Foo Smith[/url]\nHello [url=https://www.astrobin.com/users/bar/]@Bar Test[/url]" self.assertEquals(["foo", "bar"], MentionsService.get_mentions(text))
def forum_post_post_save(sender, instance, created, **kwargs): def notify_subscribers(): push_notification( list(instance.topic.subscribers.exclude(pk=instance.user.pk)), instance.user, 'new_forum_reply', { 'user': instance.user.userprofile.get_display_name(), 'user_url': settings.BASE_URL + reverse_url('user_page', kwargs={'username': instance.user}), 'post_url': build_notification_url( settings.BASE_URL + instance.get_absolute_url(), instance.user), 'topic_url': build_notification_url( settings.BASE_URL + instance.topic.get_absolute_url(), instance.user), 'topic_name': instance.topic.name, 'unsubscribe_url': build_notification_url( settings.BASE_URL + reverse_url('pybb:delete_subscription', args=[instance.topic.id]), instance.user) }) if created: mentions = MentionsService.get_mentions(instance.body) if hasattr(instance.topic.forum, 'group'): instance.topic.forum.group.save() # trigger date_updated update if get_pybb_profile(instance.user).autosubscribe and \ perms.may_subscribe_topic(instance.user, instance.topic): instance.topic.subscribers.add(instance.user) if not instance.on_moderation: notify_subscribers() else: NotificationsService.email_superusers( 'New forum post needs moderation', '%s%s' % (settings.BASE_URL, instance.get_absolute_url())) else: mentions = cache.get( "user.%d.forum_post_pre_save_mentions" % instance.user.pk, []) if cache.get("user.%d.forum_post_pre_save_approved" % instance.user.pk): notify_subscribers() for username in mentions: try: user = User.objects.get(username=username) push_notification( [user], instance.user, 'new_forum_post_mention', { 'url': build_notification_url( settings.BASE_URL + instance.get_absolute_url(), instance.user), 'user': instance.user.userprofile.get_display_name(), 'user_url': settings.BASE_URL + reverse_url( 'user_page', kwargs={'username': instance.user}), 'post': instance.topic.name, }) except User.DoesNotExist: pass cache_key = make_template_fragment_key( 'home_page_latest_from_forums', (instance.user.pk, instance.user.userprofile.language)) cache.delete(cache_key)