def output_mention_link(self, m): handle = m.group("handle") # Query user and get the link user = User.objects.filter(username=handle).first() if user: profile = reverse("user_profile", kwargs=dict(uid=user.profile.uid)) link = f'<a href="{profile}">{user.profile.name}</a>' # Subscribe mentioned users to post. if self.root: # Create user subscription if it does not already exist. auth.create_subscription(post=self.root, user=user, update=True) else: link = m.group(0) return link
def notify_watched_tags(post): """ Create a subscription to a post when """ from biostar.accounts.models import User from biostar.forum import auth # Skip non top level posts. if not post.is_toplevel: return # Iterate over tags and get users that are watching them users = [User.objects.filter(profile__watched_tags__contains=tag) for tag in post.tags.all()] # Flatten nested iterable. users = set(u for qs in users for u in qs) # Subscribe users to this post and send them emails. for user in users: auth.create_subscription(post=post.root, user=user) return
def finalize_post(sender, instance, created, **kwargs): # Determine the root of the post. root = instance.root if instance.root is not None else instance # Update last contributor, last editor, and last edit date to the thread Post.objects.filter(uid=root.uid).update( lastedit_user=instance.lastedit_user, last_contributor=instance.last_contributor, lastedit_date=instance.lastedit_date) # Get newly created subscriptions since the last edit date. subs = Subscription.objects.filter(date__gte=instance.lastedit_date, post=instance.root) if created: # Make the Uid user friendly instance.uid = instance.uid or f"p{instance.pk}" if instance.parent: # When the parent is set the root must follow the parent root. instance.root = instance.parent.root else: # When there is no parent, root and parent are set to itself. instance.root = instance.parent = instance # Answers and comments may only have comments associated with them. if instance.parent.type in (Post.ANSWER, Post.COMMENT): instance.type = Post.COMMENT # Sanity check. assert instance.root and instance.parent if instance.is_toplevel: # Add tags for top level posts. tags = [ Tag.objects.get_or_create(name=name)[0] for name in instance.parse_tags() ] instance.tags.remove() instance.tags.add(*tags) else: # Title is inherited from top level. instance.title = "%s: %s" % (instance.get_type_display(), instance.root.title[:80]) # Make the last editor first in the list of contributors # Done on post creation to avoid moderators being added for editing a post. instance.root.thread_users.remove(instance.lastedit_user) instance.root.thread_users.add(instance.lastedit_user) # Update this post rank on create and not every edit. instance.rank = instance.lastedit_date.timestamp() # Save the instance. instance.save() instance.update_parent_counts() # Bump the root rank when a new descendant is added. Post.objects.filter(uid=instance.root.uid).update( rank=util.now().timestamp()) # Create subscription to the root. auth.create_subscription(post=instance.root, user=instance.author) # Get all subscribed users when a new post is created subs = Subscription.objects.filter(post=instance.root) # Notify users who are watching tags in this post #tasks.notify_watched_tags(post=instance) # Give it a spam score. tasks.spam_scoring.spool(post=instance) # Add this post to the spam index if it's spam. tasks.update_spam_index.spool(post=instance) # Ensure posts get re-indexed after being edited. Post.objects.filter(uid=instance.uid).update(indexed=False) # Exclude current authors from receiving messages from themselves subs = subs.exclude( Q(type=Subscription.NO_MESSAGES) | Q(user=instance.author)) extra_context = dict(post=instance) tasks.notify_followers.spool(subs=subs, author=instance.author, extra_context=extra_context)
def finalize_post(sender, instance, created, **kwargs): # Determine the root of the post. root = instance.root if instance.root is not None else instance # Update last contributor, last editor, and last edit date to the thread Post.objects.filter(uid=root.uid).update( lastedit_user=instance.lastedit_user, lastedit_date=instance.lastedit_date) # Get newly created subscriptions since the last edit date. subs = Subscription.objects.filter(date__gte=instance.lastedit_date, post=instance.root) extra_context = dict() if created: # Make the uid user friendly instance.uid = instance.uid or f"9{instance.pk}" if instance.parent: # When the parent is set the root must follow the parent root. instance.root = instance.parent.root else: # When there is no parent, root and parent are set to itself. instance.root = instance.parent = instance # Answers and comments may only have comments associated with them. if instance.parent.type in (Post.ANSWER, Post.COMMENT): instance.type = Post.COMMENT # Sanity check. assert instance.root and instance.parent # Make the last editor first in the list of contributors # Done on post creation to avoid moderators being added for editing a post. instance.root.thread_users.remove(instance.lastedit_user) instance.root.thread_users.add(instance.lastedit_user) # Update this post rank on create and not every edit. instance.rank = instance.lastedit_date.timestamp() # Save the instance. instance.save() instance.update_parent_counts() # Bump the root rank when a new answer is added. if instance.is_answer: Post.objects.filter(uid=instance.root.uid).update( rank=util.now().timestamp()) # Create subscription to the root. auth.create_subscription(post=instance.root, user=instance.author) # Get all subscribed users when a new post is created subs = Subscription.objects.filter(post=instance.root) # Notify users who are watching tags in this post tasks.notify_watched_tags.spool(uid=instance.uid, extra_context=extra_context) # Send out mailing list when post is created. tasks.mailing_list.spool(uid=instance.uid, extra_context=extra_context) # Set the tags on the instance. if instance.is_toplevel: tags = [ Tag.objects.get_or_create(name=name)[0] for name in instance.parse_tags() ] instance.tags.clear() instance.tags.add(*tags) # Ensure spam posts get closed status if instance.is_spam: Post.objects.filter(uid=instance.uid).update(status=Post.CLOSED) if not instance.is_toplevel: # Title is inherited from top level. title = f"{instance.get_type_display()}: {instance.root.title[:80]}" Post.objects.filter(uid=instance.uid).update(title=title) # Ensure posts get re-indexed after being edited. Post.objects.filter(uid=instance.uid).update(indexed=False) # Exclude current authors from receiving messages from themselves subs = subs.exclude( Q(type=Subscription.NO_MESSAGES) | Q(user=instance.author)) sub_ids = list(subs.values_list('id', flat=True)) # Notify subscribers tasks.notify_followers.spool(sub_ids=sub_ids, author_id=instance.author.pk, uid=instance.uid, extra_context=extra_context)