def build_child_tree(root_node, user): # Get the list of child of this node. nodes = list(itertools.chain.from_iterable(root_node.values())) nodeElements = [] # Create <li> nodes for each. for node in nodes: nodeElement = ElementTree.Element('li') nodeElement.set('class', 'post-comment') # If this child has other children, build child tree. if type(node) is dict: root_node = get_root_key(node) (host_type, host, root) = CommentUtilities.get_comment_root(root_node) add_comment_data_to_element(root_node, nodeElement, user, host, host_type) nodeList = ElementTree.SubElement(nodeElement, 'ul') child_nodes = build_child_tree(node, user) for child_node in child_nodes: nodeList.append(child_node) # Otherwise, append a child <a> element as is. else: (host_type, host, root) = CommentUtilities.get_comment_root(node) add_comment_data_to_element(node, nodeElement, user, host, host_type) nodeElements.append(nodeElement) return nodeElements
def delete_comment(request, comment_id): try: comment = Comment.objects.get(pk=comment_id) # TODO(Varun): Same logic as duplicated from template generation to show # delete button from interactions.CommentUtilities import CommentUtilities (host_type, host, root) = CommentUtilities.get_comment_root(comment) if host_type.name == 'project': if request.user == comment.user or request.user in host.admins.all(): # Delete all descendant elements of this comment. delete_comment_tree(comment) return APIUtilities._api_success() else: return APIUtilities._api_unauthorized_failure() elif host_type.name == 'resource': if request.user == comment.user or ( request.user in host.collaborators.all() or request.user == host.creator): delete_comment_tree(comment) return APIUtilities._api_success() return APIUtilities._api_failure() except Comment.DoesNotExist: return APIUtilities._api_not_found()
def test_post_new_nested_comment(self): # Fetch discussion post response through unique body_markdown. existing_comment = Comment.objects.get( body_markdown='This is my response to the first post') new_comment_body = 'This is a response to the comment on the post #1' from django.contrib.contenttypes.models import ContentType comment_ct = ContentType.objects.get_for_model(Comment) # Post the new comment on the discussion post. post_response = self.client.post('/interactions/comment/', { 'parent_id': existing_comment.id, 'user': 1, 'parent_type': comment_ct.id, 'body_markdown': new_comment_body }) self.assertEqual(post_response.status_code, 200) # Get newly created comment. import json comment_id = json.loads(post_response.content)['message']['id'] new_comment = Comment.objects.get(pk=comment_id) from interactions.CommentUtilities import CommentUtilities (root_type, root, root_child) = CommentUtilities.get_comment_root(new_comment) # Now load the discussion page and see if the new comment is there as # a response to the root thread post. response = self.client.get( '/project/pps-got-magic/discussion/' + str(root_child.id) + '/') post_comments = response.context['post'].comments self.assertIn(new_comment, post_comments[root_child][0][existing_comment])
def project_comment_vote_notification(sender, **kwargs): vote = kwargs.get('vote', None) notification = Notification() notification.user = vote.parent.user # Get the discussion post. from interactions.CommentUtilities import CommentUtilities (host_type, host, discussion) = CommentUtilities.get_comment_root(vote.parent) # TODO(Varun): Don't notify if the parent creator and vote creator are the same. notification.url = reverse( 'projects:project_discussion', kwargs={ 'project_slug': host.slug, 'discussion_id': discussion.id } ) from oer.BeautifulSoup import BeautifulSoup soup = BeautifulSoup(vote.parent.body_markdown) comment_body = soup.text[:50] + "..." if len(soup.text) >= 50 else soup.text notification.description = "%s just upvoted your comment \"%s\" in %s" % ( vote.user.get_full_name(), comment_body, host.title) notification.save()
def new_comment_activity(sender, **kwargs): comment_id = kwargs.get('comment_id', None) parent_type_id = kwargs.get('parent_type_id', None) # Get the commment. from interactions.models import Comment comment = Comment.objects.get(pk=comment_id) # Get the type of the parent of the comment from django.contrib.contenttypes.models import ContentType parent_ct = ContentType.objects.get(pk=parent_type_id) if parent_ct.name == 'resource': import oer.ResourceUtilities as ru (resource_root_type, resource_root) = ru.get_resource_root(comment.parent) if resource_root_type.name == 'project': new_activity = Activity( actor=comment.user, action=comment, target=comment.parent, context=resource_root ) new_activity.save() elif resource_root_type.name == 'user profile': new_activity = Activity( actor=comment.user, action=comment, target=comment.parent, context=resource_root ) new_activity.save() if parent_ct.name == 'comment' or parent_ct.name == 'project': # Get root parent of the comment from interactions.CommentUtilities import CommentUtilities (root_parent_type, root_parent, root_comment) = CommentUtilities.get_comment_root(comment) # If this is the child of a comment if parent_ct.name == 'project': new_activity = Activity( actor=comment.user, action=comment, target=comment, context=root_parent ) new_activity.save() # If this is the child of a comment elif parent_ct.name == 'comment': if root_parent_type.name == 'project': new_activity = Activity( actor=comment.user, action=comment, target=root_comment, context=root_parent ) new_activity.save() if parent_ct.name == 'project' or ( parent_ct.name == 'comment' and root_parent_type.name == 'project'): recipients = None if root_parent.visibility == 'public': # Get all people subscribed to comment creator. subscriptions = Subscription.objects.filter( subscribee=comment.user.get_profile()) if subscriptions.count() >= 1: recipients = [x.subscriber.user for x in subscriptions] elif root_parent.visibility == 'private': project_members = root_parent.confirmed_members if len(project_members) >= 1: recipients = project_members if recipients: for recipient in recipients: new_activity.recipients.add(recipient) if parent_ct.name == 'resource': recipients = None subscriptions = Subscription.objects.filter( subscribee=comment.user.get_profile()) if subscriptions.count() >= 1: recipients = [x.subscriber.user for x in subscriptions] if comment.parent.visibility == 'private': recipients = [user for user in recipients if user in comment.parent.collaborators.all()] if recipients: for recipient in recipients: new_activity.recipients.add(recipient)
def add_comment_notification(sender, **kwargs): comment_id = kwargs.get('comment_id', None) parent_type_id = kwargs.get('parent_type_id', None) host = kwargs.get('host', None) # Get the commment. from interactions.models import Comment, CommentReference comment = Comment.objects.get(pk=comment_id) # Get the type of the parent of the comment from django.contrib.contenttypes.models import ContentType parent_ct = ContentType.objects.get(pk=parent_type_id) if parent_ct.name == 'comment reference': # Notify a consolidated list of (1) the collaborators on the resource, # (2) the previous commentors on the document element reference item. from oer.models import Document, DocumentElement, ResourceRevision from django.contrib.contenttypes.models import ContentType document_content_type = ContentType.objects.get_for_model(Document) document_element_content_type = ContentType.objects.get_for_model(DocumentElement) # Get the resource on whose (document element) this comment was created. document = comment.parent.owner.document resourcerevision = ResourceRevision.objects.get( content_id=document.id, content_type=document_content_type) # Get all other comments that have been made on document element reference item. # Exclude the current comment reference (crashed anyways because comment not assigned). comment_references = CommentReference.objects.filter( owner_type=document_element_content_type, owner_id=comment.parent.owner.id, reference=comment.parent.reference ).exclude(pk=comment.parent.id) comment_users = map(lambda x: x.comment.user, comment_references) users_to_notify = set(resourcerevision.resource.collaborators.all()) | set(comment_users) try: # Remove the creator of the comment from the list of users to notify if he/she # is a collaborator. users_to_notify.remove(comment.user) except: pass for user in users_to_notify: notification = Notification() notification.user = user notification.url = reverse( 'read', kwargs={ 'resource_id': resourcerevision.resource.id, 'resource_slug': resourcerevision.resource.slug } ) notification.description = "%s commented on the contents of %s: \"%s\"" % ( comment.user.get_full_name(), resourcerevision.resource.title, comment.body_markdown[:100]) notification.save() # Send an email about this notification. nu.notify_by_email(notification, host) elif parent_ct.name == 'comment' or parent_ct.name == 'resource' or parent_ct.name == 'article revision': # Determine whether this is an ArticleRevision, resource, etc. and the # user who created it. asset = comment.parent user_to_notify = asset.user # If the commentor is not the same as the creator of the original post if user_to_notify != comment.user: notification = Notification() notification.user = user_to_notify # If this is the child of a comment if parent_ct.name == 'comment': # Get root parent of the comment from interactions.CommentUtilities import CommentUtilities (root_parent_type, root_parent, root_comment) = CommentUtilities.get_comment_root(comment) else: root_parent = comment.parent root_parent_type = parent_ct root_comment = comment if root_parent_type.name == 'article revision': from articles import views breadcrumb = views.fetch_cached_breadcrumb(asset) category_slug = [x.slug for x in breadcrumb[1:]] notification.url = reverse( 'articles:reader', kwargs={'category_slug': '/'.join(category_slug)} ) + "?q=%s&revision=%s" % (asset.article.slug, str(asset.id)) notification.description = "%s commented on %s: \"%s\"" % ( comment.user.get_full_name(), asset.title, comment.body_markdown[:100]) elif root_parent_type.name == 'project': notification.url = reverse( 'projects:project_discussion', kwargs={ 'project_slug': root_parent.slug, 'discussion_id': root_comment.id } ) notification.description = "%s commented on your post in %s: \"%s\"" % ( comment.user.get_full_name(), root_parent.title, comment.body_markdown[:100]) elif root_parent_type.name == 'resource': import oer.ResourceUtilities as ru (resource_root_type, resource_root) = ru.get_resource_root(root_parent) if resource_root_type.name == 'project': notification.url = reverse( 'projects:read_project_resource', kwargs={ 'project_slug': resource_root.slug, 'resource_id': root_parent.id, 'resource_slug': root_parent.slug } ) elif resource_root_type.name == 'user profile': notification.url = reverse( 'read', kwargs={ 'resource_id': root_parent.id, 'resource_slug': root_parent.slug } ) notification.description = "%s commented on your post in %s: \"%s\"" % ( comment.user.get_full_name(), root_parent.title, comment.body_markdown[:100]) notification.save() # Send an email about this notification. nu.notify_by_email(notification, host) elif parent_ct.name == 'project': project_members = comment.parent.members.all().exclude(pk=comment.user.id) for member in project_members: notification = Notification() notification.user = member notification.url = reverse( 'projects:project_discussion', kwargs={ 'project_slug': comment.parent.slug, 'discussion_id': comment.id } ) notification.description = "%s wrote a new post in %s: \"%s\"" % ( comment.user.get_full_name(), comment.parent.title, comment.body_markdown[:100]) notification.save()