# Path: core/models.py
# class Content(models.Model):
#     """
#     Abstract model for website content.
# 
#     Content models should be subclassed to create models for user content such
#     as proposals and comments which can be voted on, ranked and moderated.
# 
#     :ivar id:            Primary key for content subclasses
#     :ivar createdAt:     DateTime of creation
#     :ivar lastModified:  DateTime of last modification
#     :ivar user:          Creator of content
#     :ivar upVotes:       Up vote count, set by save method of Vote model(only!)
#     :ivar downVotes:     Down vote count, set by :meth:``votes.Vote.save``\
#                          (only!)
#     :ivar isHidden:      True if the content has been hidden, set by save\
#                          method of HideAction (only!)
#     :ivar rank:          Rank of the content for ordering by popularity, set\
#                          by cron job
# 
#     """
#     id = models.AutoField(primary_key=True)
#     createdAt = models.DateTimeField(auto_now_add=True)
#     lastModified = models.DateTimeField(auto_now=True)
#     user = models.ForeignKey(settings.AUTH_USER_MODEL)
#     upVotes = models.IntegerField(default=0)
#     downVotes = models.IntegerField(default=0)
#     isHidden = models.BooleanField(default=False)
#     rank = models.FloatField(default=0.0)
# 
#     def get_votes_count(self, isUp):
#         """
#         Query vote table and return number of either up or down votes.
# 
#         :rtype: integer
#         """
#         return self.votes.filter(isVoteUp=isUp).count()
# 
#     def get_voters(self, target="all"):
#         """
#         Get users who have voted on this content.
# 
#         :param target: ``"all"`` (default) for all users, ``"up"``\
#                        for voters for and ``"down"`` for voters against
#         :rtype: QuerySet
#         """
#         content_type = ContentType.objects.get_for_model(self)
#         users = get_user_model().objects\
#                                 .filter(votes__content_type=content_type)\
#                                 .filter(votes__object_id=self.id)
#         if target == "all":
#             return users
#         elif target == "up":
#             return users.filter(votes__isVoteUp=True)
#         elif target == "down":
#             return users.filter(votes__isVoteUp=False)
# 
#     class Meta:
#         abstract = True
# 
# Path: core/utils.py
# def replace_bad_words(value):
#     """Replace words in ``value`` found in ``settings.PROFANITIES_LIST`` with
#     dashes
# 
#     :type value: string
#     :returns: ``value`` without profanities
#     :rtype: string
# 
#     """
#     # Replaces profanities in strings with %#!&!
#     replacement_symbols = "%&$?!"
#     words = re.sub(r"[^\w]", " ", value).split()
#     bad_words_seen = []
#     for word in words:
#         if word.lower() in settings.PROFANITIES_LIST:
#             bad_words_seen.append(word)
#     if bad_words_seen:
#         for word in bad_words_seen:
#             replacement = "".join([random.choice(replacement_symbols)
#                                    for i in range(len(word))])
#             value = value.replace(word, replacement)
#     return value
# 
# Path: votes/models.py
# class Vote(models.Model):
#     isVoteUp = models.BooleanField(default=False)
#     createdAt = models.DateTimeField(auto_now_add=True)
#     user = models.ForeignKey(settings.AUTH_USER_MODEL, related_name="votes")
# 
#     content_type = models.ForeignKey(ContentType)
#     object_id = models.PositiveIntegerField()
#     content = GenericForeignKey()
# 
#     objects = VoteManager()
# 
#     def save(self, *args, **kwargs):
#         super(Vote, self).save(*args, **kwargs)
#         self.content.upVotes = Vote.objects.get_votes_count(self.content, True)
#         self.content.downVotes = Vote.objects.get_votes_count(self.content,
#                                                               False)
#         self.content.save()
# 
#     def delete(self, *args, **kwargs):
#         if self.isVoteUp:
#             self.content.upVotes = Vote.objects.get_votes_count(self.content,
#                                                                 True) - 1
#         else:
#             self.content.downVotes = Vote.objects.get_votes_count(self.content,
#                                                                   False) - 1
#         self.content.save()
#         super(Vote, self).delete(*args, **kwargs)
# 
#     def get_content_type():
#         if not hasattr(Vote, '_content_type'):
#             Vote._content_type = ContentType.objects.get(
#                 app_label="votes", model="vote")
#         return Vote._content_type


import datetime
from django.db import models
from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes.generic import GenericRelation
from core.models import Content
from core.utils import replace_bad_words
from votes.models import Vote
        if sort == "popularity":
            return sorted(comments, key=lambda c: c.get_score(), reverse=True)
        elif sort == "newest":
            return sorted(comments, key=lambda c: c.createdAt)


class Comment(Content):
    # The maximum length of 'text' is 6100 because a proposal can have 6000
    # characters in its body and 100 in its title. Because amendments are
    # stored as Comments, they must be at least as long as Proposals.
    text = models.CharField(max_length=6100)
    proposal = models.ForeignKey('proposals.Proposal', null=False,
                                 related_name="comments")
    replyTo = models.ForeignKey("self", null=True)
    isAmendment = models.BooleanField(default=False)
    votes = GenericRelation(Vote)

    objects = CommentManager()

    def get_content_type():
        if not hasattr(Comment, '_content_type'):
            Comment._content_type = ContentType.objects.get(
                app_label="comments", model="comment")
        return Comment._content_type

    def save(self, *args, **kwargs):
        is_initial = not self.pk
        super(Comment, self).save(*args, **kwargs)
        # when the comment is first created, add a vote by the commenter
        if is_initial:

# Path: core/models.py
# class Content(models.Model):
#     """
#     Abstract model for website content.
# 
#     Content models should be subclassed to create models for user content such
#     as proposals and comments which can be voted on, ranked and moderated.
# 
#     :ivar id:            Primary key for content subclasses
#     :ivar createdAt:     DateTime of creation
#     :ivar lastModified:  DateTime of last modification
#     :ivar user:          Creator of content
#     :ivar upVotes:       Up vote count, set by save method of Vote model(only!)
#     :ivar downVotes:     Down vote count, set by :meth:``votes.Vote.save``\
#                          (only!)
#     :ivar isHidden:      True if the content has been hidden, set by save\
#                          method of HideAction (only!)
#     :ivar rank:          Rank of the content for ordering by popularity, set\
#                          by cron job
# 
#     """
#     id = models.AutoField(primary_key=True)
#     createdAt = models.DateTimeField(auto_now_add=True)
#     lastModified = models.DateTimeField(auto_now=True)
#     user = models.ForeignKey(settings.AUTH_USER_MODEL)
#     upVotes = models.IntegerField(default=0)
#     downVotes = models.IntegerField(default=0)
#     isHidden = models.BooleanField(default=False)
#     rank = models.FloatField(default=0.0)
# 
#     def get_votes_count(self, isUp):
#         """
#         Query vote table and return number of either up or down votes.
# 
#         :rtype: integer
#         """
#         return self.votes.filter(isVoteUp=isUp).count()
# 
#     def get_voters(self, target="all"):
#         """
#         Get users who have voted on this content.
# 
#         :param target: ``"all"`` (default) for all users, ``"up"``\
#                        for voters for and ``"down"`` for voters against
#         :rtype: QuerySet
#         """
#         content_type = ContentType.objects.get_for_model(self)
#         users = get_user_model().objects\
#                                 .filter(votes__content_type=content_type)\
#                                 .filter(votes__object_id=self.id)
#         if target == "all":
#             return users
#         elif target == "up":
#             return users.filter(votes__isVoteUp=True)
#         elif target == "down":
#             return users.filter(votes__isVoteUp=False)
# 
#     class Meta:
#         abstract = True
# 
# Path: core/utils.py
# def replace_bad_words(value):
#     """Replace words in ``value`` found in ``settings.PROFANITIES_LIST`` with
#     dashes
# 
#     :type value: string
#     :returns: ``value`` without profanities
#     :rtype: string
# 
#     """
#     # Replaces profanities in strings with %#!&!
#     replacement_symbols = "%&$?!"
#     words = re.sub(r"[^\w]", " ", value).split()
#     bad_words_seen = []
#     for word in words:
#         if word.lower() in settings.PROFANITIES_LIST:
#             bad_words_seen.append(word)
#     if bad_words_seen:
#         for word in bad_words_seen:
#             replacement = "".join([random.choice(replacement_symbols)
#                                    for i in range(len(word))])
#             value = value.replace(word, replacement)
#     return value
# 
# Path: votes/models.py
# class Vote(models.Model):
#     isVoteUp = models.BooleanField(default=False)
#     createdAt = models.DateTimeField(auto_now_add=True)
#     user = models.ForeignKey(settings.AUTH_USER_MODEL, related_name="votes")
# 
#     content_type = models.ForeignKey(ContentType)
#     object_id = models.PositiveIntegerField()
#     content = GenericForeignKey()
# 
#     objects = VoteManager()
# 
#     def save(self, *args, **kwargs):
#         super(Vote, self).save(*args, **kwargs)
#         self.content.upVotes = Vote.objects.get_votes_count(self.content, True)
#         self.content.downVotes = Vote.objects.get_votes_count(self.content,
#                                                               False)
#         self.content.save()
# 
#     def delete(self, *args, **kwargs):
#         if self.isVoteUp:
#             self.content.upVotes = Vote.objects.get_votes_count(self.content,
#                                                                 True) - 1
#         else:
#             self.content.downVotes = Vote.objects.get_votes_count(self.content,
#                                                                   False) - 1
#         self.content.save()
#         super(Vote, self).delete(*args, **kwargs)
# 
#     def get_content_type():
#         if not hasattr(Vote, '_content_type'):
#             Vote._content_type = ContentType.objects.get(
#                 app_label="votes", model="vote")
#         return Vote._content_type


# Path: comments/models.py
import datetime
from django.db import models
from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes.generic import GenericRelation
from core.models import Content
from core.utils import replace_bad_words
from votes.models import Vote

        if sort == "popularity":
            return sorted(comments, key=lambda c: c.get_score(), reverse=True)
        elif sort == "newest":
            return sorted(comments, key=lambda c: c.createdAt)


class Comment(Content):
    # The maximum length of 'text' is 6100 because a proposal can have 6000
    # characters in its body and 100 in its title. Because amendments are
    # stored as Comments, they must be at least as long as Proposals.
    text = models.CharField(max_length=6100)
    proposal = models.ForeignKey('proposals.Proposal', null=False,
                                 related_name="comments")
    replyTo = models.ForeignKey("self", null=True)
    isAmendment = models.BooleanField(default=False)
    votes = GenericRelation(Vote)

    objects = CommentManager()

    def get_content_type():
        if not hasattr(Comment, '_content_type'):
            Comment._content_type = ContentType.objects.get(
                app_label="comments", model="comment")
        return Comment._content_type

    def save(self, *args, **kwargs):
        is_initial = not self.pk
        super(Comment, self).save(*args, **kwargs)
        # when the comment is first created, add a vote by the commenter
        if is_initial:

            Vote.objects.create(user=self.user, content=self, isVoteUp=True)