Example #1
0
def get_posts(user, topic="", tag="", order="rank", limit=None):
    """
    Generates a post list on a topic.
    """
    # Topics are case insensitive.
    topic = topic.lower()

    # Detect known post types.
    post_type = POST_TYPE_MAPPER.get(topic)

    # Determines how to start the query.
    if post_type:
        query = Post.objects.filter(type=post_type)
    elif topic == OPEN:
        query = Post.objects.filter(type=Post.QUESTION, reply_count=0)
    elif topic == BOOKMARKS and user.is_authenticated:
        query = Post.objects.filter(votes__author=user,
                                    votes__type=Vote.BOOKMARK)
    elif topic == FOLLOWING and user.is_authenticated:
        query = Post.objects.exclude(
            subs__type=Subscription.NO_MESSAGES).filter(subs__user=user)
    elif topic == MYPOSTS and user.is_authenticated:
        query = Post.objects.filter(author=user)
    elif topic == MYVOTES:
        #TODO: switching to votes
        #votes_query = Vote.objects.filter(post__author=user).exclude(author=user)
        #query = votes_query.values("post")
        query = Post.objects.filter(votes__post__author=user).exclude(
            votes__author=user)
    else:
        query = Post.objects.filter(type__in=Post.TOP_LEVEL)

    # Filter by tags if specified.
    if tag:
        query = query.filter(tag_val__iregex=tag)

    # Apply post ordering.
    if ORDER_MAPPER.get(order):
        ordering = ORDER_MAPPER.get(order)
        query = query.order_by(ordering)
    else:
        query = query.order_by("-rank")

    days = LIMIT_MAP.get(limit, 0)
    # Apply time limit if required.
    if days:
        delta = util.now() - timedelta(days=days)
        query = query.filter(lastedit_date__gt=delta)

    # Select related information used during rendering.
    query = query.prefetch_related("root", "author__profile",
                                   "lastedit_user__profile",
                                   "thread_users__profile")

    return query
Example #2
0
def bump(request, post, **kwargs):
    now = util.now()
    user = request.user

    Post.objects.filter(uid=post.uid).update(lastedit_date=now, rank=now.timestamp())
    msg = f"bumped post"
    url = post.get_absolute_url()
    messages.info(request, mark_safe(msg))
    auth.db_logger(user=user, text=f"{msg}", post=post)

    return url
Example #3
0
def fake():
    """
    Create a fake blog post.
    """

    # Get or create a blog
    blog, created = Blog.objects.get_or_create(title="Fake")

    BlogPost.objects.create(blog=blog,
                            title='Creating a fake blog post.',
                            creation_date=now())
Example #4
0
def get_posts(user, topic="", tag="", order="", limit=None):
    """
    Generates a post list on a topic.
    """
    # Topics are case insensitive.
    topic = topic or LATEST
    topic = topic.lower()

    # Detect known post types.
    post_type = POST_TYPE_MAPPER.get(topic)
    query = Post.objects.valid_posts(u=user, is_toplevel=True)

    # Determines how to start the preform_search.
    if post_type:
        query = query.filter(type=post_type)
    elif topic == OPEN:
        query = query.filter(type=Post.QUESTION, answer_count=0)
    elif topic == BOOKMARKS and user.is_authenticated:
        query = query.filter(votes__author=user, votes__type=Vote.BOOKMARK)
    elif topic == FOLLOWING and user.is_authenticated:
        query = query.filter(subs__user=user)
    elif topic == MYPOSTS and user.is_authenticated:
        query = query.filter(author=user)
    elif topic == MYVOTES and user.is_authenticated:
        query = query.filter(votes__post__author=user)
    elif topic == MYTAGS and user.is_authenticated:
        tags = user.profile.my_tags.split(",")
        query = query.filter(tags__name__in=tags)

    if user.is_anonymous or not user.profile.is_moderator:
        query = query.exclude(Q(spam=Post.SPAM) | Q(status=Post.DELETED))
    # Filter by tags if specified.
    if tag:
        query = query.filter(tags__name=tag.lower())

    # Apply post ordering.
    if ORDER_MAPPER.get(order):
        ordering = ORDER_MAPPER.get(order)
        query = query.order_by(ordering)
    else:
        query = query.order_by("-rank")

    days = LIMIT_MAP.get(limit, 0)
    # Apply time limit if required.
    if days:
        delta = util.now() - timedelta(days=days)
        query = query.filter(lastedit_date__gt=delta)

    # Select related information used during rendering.
    query = query.select_related("root").select_related(
        "author__profile", "lastedit_user__profile")

    return query
def init_local(update):
    """
    Creates a local blog
    """
    blog, created = Blog.objects.get_or_create(title="Local blog",
                                               remote=False)
    for step in range(update):
        logger.info("adding local blog post")
        BlogPost.objects.create(blog=blog,
                                title='Local blog post',
                                content="Lorem ipsum",
                                creation_date=now())
Example #6
0
def get_start(days):
    """
    Return the start date stored in cache.
    """

    if days < 0:
        recent = Sync.objects.filter(pk=1).first()
        recent = recent.last_synced if recent else None
    else:
        recent = Post.objects.old().order_by('-creation_date').first()
        recent = recent.creation_date if recent else None

    start = recent or util.now()

    return start
Example #7
0
def get_start(days, cursor):
    """
    Return the start date stored in database
    """

    if days < 0:
        recent = Sync.objects.filter(pk=1).first()
        recent = recent.last_synced if recent else most_recent(cursor=cursor)
        recent = recent + timedelta(days=2)
    else:
        # Get the most recently created post on the remote server.
        recent = Post.objects.old().order_by('-creation_date').first()
        recent = recent.creation_date if recent else None
        recent = recent - timedelta(days=2)

    start = recent or util.now()

    return start
Example #8
0
def create_user_awards(user_id):

    from biostar.accounts.models import User
    from biostar.forum.models import Award, Badge, Post
    from biostar.forum.awards import ALL_AWARDS
    from biostar.forum import util

    user = User.objects.filter(id=user_id).first()
    # debugging
    # Award.objects.all().delete()

    # Collect valid targets
    valid = []

    for award in ALL_AWARDS:

        # Valid award targets the user has earned
        targets = award.validate(user)
        for target in targets:

            date = util.now()
            post = target if isinstance(target, Post) else None
            badge = Badge.objects.filter(name=award.name).first()

            # Do not award a post multiple times.
            already_awarded = Award.objects.filter(user=user,
                                                   badge=badge,
                                                   post=post).exists()
            if post and already_awarded:
                continue

            valid.append((user, badge, date, post))

    # Pick random awards to give to user
    random.shuffle(valid)

    valid = valid[:settings.MAX_AWARDS]

    for target in valid:
        user, badge, date, post = target

        # Create an award for each target.
        Award.objects.create(user=user, badge=badge, date=date, post=post)
        message(f"award {badge.name} created for {user.email}")
Example #9
0
def apply_sort(posts, limit=None, order=None):
    # Apply post ordering.
    if ORDER_MAPPER.get(order):
        ordering = ORDER_MAPPER.get(order)
        posts = posts.order_by(ordering)
    else:
        posts = posts.order_by('-rank')

    days = LIMIT_MAP.get(limit, 0)
    # Apply time limit if required.
    if days:
        delta = util.now() - timedelta(days=days)
        posts = posts.filter(lastedit_date__gt=delta)

    # Select related information used during rendering.
    posts = posts.select_related("root").select_related(
        "author__profile", "lastedit_user__profile")

    return posts
Example #10
0
    def edit(self):
        """
        Edit an existing post.
        """
        if self.user != self.post.author and not self.user.profile.is_moderator:
            raise forms.ValidationError("Only the author or a moderator can edit a post.")
        data = self.cleaned_data

        self.post.title = data.get('title')
        content = data.get('content', self.post.content)

        log_edits(user=self.user, post=self.post)
        self.post.content = content

        self.post.type = data.get('post_type')
        self.post.tag_val = data.get('tag_val')
        self.post.lastedit_date = util.now()
        self.post.lastedit_user = self.user
        self.post.save()
        return self.post
Example #11
0
def community_list(request):

    users = User.objects.select_related("profile")

    page = request.GET.get("page", 1)
    ordering = request.GET.get("order", "visit")
    limit_to = request.GET.get("limit", "time")
    query = request.GET.get('query', '')
    query = query.replace("'", "").replace('"', '').strip()

    days = LIMIT_MAP.get(limit_to, 0)

    if days:
        delta = util.now() - timedelta(days=days)
        users = users.filter(profile__last_login__gt=delta)

    if query and len(query) > 2:
        db_query = Q(profile__name__icontains=query) | Q(profile__uid__icontains=query) | \
                   Q(username__icontains=query) | Q(email__icontains=query)
        users = users.filter(db_query)

    # Remove the cache when filters are given.
    no_cache = days or (query and len(query) > 2) or ordering
    cache_key = None if no_cache else USERS_LIST_KEY

    order = ORDER_MAPPER.get(ordering, "visit")
    users = users.filter(profile__state__in=[Profile.NEW, Profile.TRUSTED])
    users = users.order_by(order)

    # Create the paginator
    paginator = CachedPaginator(cache_key=cache_key,
                                object_list=users,
                                per_page=settings.POSTS_PER_PAGE)
    users = paginator.get_page(page)
    context = dict(tab="community",
                   users=users,
                   query=query,
                   order=ordering,
                   limit=limit_to)

    return render(request, "community_list.html", context=context)
Example #12
0
def community_list(request):
    users = User.objects.select_related("profile")
    page = request.GET.get("page", 1)
    ordering = request.GET.get("order", "visit")
    limit_to = request.GET.get("limit", "time")
    days = LIMIT_MAP.get(limit_to, 0)

    if days:
        delta = util.now() - timedelta(days=days)
        users = users.filter(profile__last_login__gt=delta)

    order = ORDER_MAPPER.get(ordering, "visit")
    users = users.order_by(order)

    paginator = Paginator(users, settings.USERS_PER_PAGE)
    users = paginator.get_page(page)
    context = dict(community="active",
                   objs=users,
                   order=ordering,
                   limit=limit_to)

    return render(request, "community_list.html", context=context)
Example #13
0
def herald_publisher(request, limit=20, nmin=1):
    """
    Create one publication from Herald accepted submissions ( up to 'limit' ).
    """

    # Reset status on published links.
    # SharedLink.objects.filter(status=SharedLink.PUBLISHED).update(status=SharedLink.ACCEPTED)

    heralds = SharedLink.objects.filter(
        status=SharedLink.ACCEPTED).order_by('-pk')[:limit]
    count = heralds.count()

    if count < nmin:
        logger.warning(
            f"Not enough stories to publish, minimum of {nmin} required.")
        return

    # Create herald content
    date = util.now()

    date_fmt = date.strftime("%A, %B %d, %Y")

    title = f"The Biostar Herald for {date_fmt}"

    port = f':{settings.HTTP_PORT}' if settings.HTTP_PORT else ''

    base_url = f"{settings.PROTOCOL}://{settings.SITE_DOMAIN}{port}"
    authors = set(h.author for h in heralds)
    editors = set(h.editor for h in heralds)

    subscribe_url = reverse('herald_subscribe')
    context = dict(heralds=heralds,
                   title=title,
                   site_domain=settings.SITE_DOMAIN,
                   protocol=settings.PROTOCOL,
                   base_url=base_url,
                   authors=authors,
                   editors=editors,
                   subscribe_url=subscribe_url)

    content = render_template(template="herald/herald_content.md",
                              context=context)

    # Create herald post
    user = User.objects.filter(is_superuser=True).first()
    post = auth.create_post(title=title,
                            content=content,
                            author=user,
                            tag_val='herald',
                            ptype=Post.HERALD,
                            nodups=False,
                            request=request)

    # Tie these submissions to herald post
    hpks = heralds.values_list('pk', flat=True)
    SharedLink.objects.filter(pk__in=hpks).update(status=SharedLink.PUBLISHED,
                                                  post=post,
                                                  lastedit_date=date)

    # Log the action
    auth.db_logger(user=user, text=f"published {count} submissions in {title}")

    # Create a herald blog post
    herald_blog(post=post)

    # Send out herald emails
    herald_emails.spool(uid=post.uid)

    # Clean up declined links
    remove_declined()

    return post
Example #14
0
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)
Example #15
0
 def save(self, *args, **kwargs):
     self.sent_date = self.sent_date or util.now()
     self.uid = self.uid or util.get_uuid(limit=16)
     super(Message, self).save(**kwargs)
Example #16
0
def past_date(days=2, minutes=0, seconds=0):
    return util.now() - timedelta(days=days, minutes=minutes, seconds=seconds)
Example #17
0
def get_posts(user, topic="", tag="", order="", limit=None):
    """
    Generates a post list on a topic.
    """
    # Topics are case insensitive.
    topic = topic or LATEST
    topic = topic.lower()

    # Detect known post types.
    post_type = POST_TYPE_MAPPER.get(topic)
    query = Post.objects.valid_posts(u=user, is_toplevel=True)

    # Determines how to start the preform_search.
    if post_type:
        query = query.filter(type=post_type)

    elif topic == SHOW_SPAM:
        query = query.filter(Q(spam=Post.SPAM) | Q(spam=Post.SUSPECT))
    elif topic == OPEN:
        query = query.filter(type=Post.QUESTION, answer_count=0)
    elif topic == BOOKMARKS and user.is_authenticated:
        query = query.filter(votes__author=user, votes__type=Vote.BOOKMARK)
    elif topic == FOLLOWING and user.is_authenticated:
        query = query.filter(subs__user=user).exclude(
            subs__type=Subscription.NO_MESSAGES)
    elif topic == MYPOSTS and user.is_authenticated:
        # Show users all of there posts ( deleted, spam, or quarantined )
        query = Post.objects.filter(author=user)
        #query = query.filter(author=user)

    elif topic == MYVOTES and user.is_authenticated:
        query = query.filter(votes__post__author=user)
    elif topic == MYTAGS and user.is_authenticated:
        tags = map(lambda t: t.lower(), user.profile.my_tags.split(","))
        query = query.filter(tags__name__in=tags).distinct()
    else:
        # Exclude spam posts unless specifically on the tab.
        query = query.exclude(Q(spam=Post.SPAM))

    # Filter by tags if specified.
    if tag:
        query = query.filter(tags__name=tag.lower())

    # Apply post ordering.
    if ORDER_MAPPER.get(order):
        ordering = ORDER_MAPPER.get(order)
        query = query.order_by(ordering)
    else:
        query = query.order_by("-rank")

    days = LIMIT_MAP.get(limit, 0)
    # Apply time limit if required.
    if days:
        delta = util.now() - timedelta(days=days)
        query = query.filter(lastedit_date__gt=delta)

    # Select related information used during rendering.
    query = query.select_related("root").select_related(
        "author__profile", "lastedit_user__profile")

    return query
Example #18
0
def get_posts(request, topic="", order="", limit=None):
    """
    Generates a post list on a topic.
    """

    user = request.user
    # Topics are case insensitive.
    topic = topic or LATEST
    topic = topic.lower()

    # Detect known post types.
    post_type = POST_TYPE.get(topic)

    # Get all open top level posts.
    posts = Post.objects.filter(is_toplevel=True, root__status=Post.OPEN)

    # Filter for various post types.
    if post_type:
        posts = posts.filter(type=post_type)

    elif topic == SHOW_SPAM and user.profile.is_moderator:
        posts = get_spam(request)

    elif topic == OPEN:
        posts = posts.filter(type=Post.QUESTION, answer_count=0)

    elif topic == BOOKMARKS and user.is_authenticated:
        posts = Post.objects.filter(votes__author=user,
                                    votes__type=Vote.BOOKMARK)

    elif topic == FOLLOWING and user.is_authenticated:
        posts = posts.filter(subs__user=user).exclude(
            subs__type=Subscription.NO_MESSAGES)

    elif topic == MYPOSTS and user.is_authenticated:
        # Show users all of their posts ( deleted, spam, or quarantined )
        posts = Post.objects.filter(author=user)

    elif topic == MYVOTES and user.is_authenticated:
        posts = posts.filter(votes__post__author=user)

    elif topic == MYTAGS and user.is_authenticated:
        tags = map(lambda t: t.lower(), user.profile.my_tags.split(","))
        posts = posts.filter(tags__name__in=tags).distinct()

    # Search for tags
    elif topic != LATEST and (topic not in POST_TYPE):
        posts = posts.filter(tags__name=topic.lower())
        messages.success(request, f"Filtering for tag: {topic}")

    # Apply post ordering.
    if ORDER_MAPPER.get(order):
        ordering = ORDER_MAPPER.get(order)
        posts = posts.order_by(ordering)
    else:
        posts = posts.order_by("-rank")

    days = LIMIT_MAP.get(limit, 0)
    # Apply time limit if required.
    if days:
        delta = util.now() - timedelta(days=days)
        posts = posts.filter(lastedit_date__gt=delta)

    # Select related information used during rendering.
    posts = posts.select_related("root").select_related(
        "author__profile", "lastedit_user__profile")

    return posts
def time_ago(days=2, minutes=0, seconds=0):
    return util.now() - timedelta(days=days, minutes=minutes, seconds=seconds)
Example #20
0
 def items(self):
     # Delay posts hours.
     delay_time = now() - timedelta(hours=2)
     posts = Post.objects.valid_posts(creation_date__lt=delay_time).exclude(
         type=Post.BLOG).order_by('-creation_date')
     return posts[:FEED_COUNT]
Example #21
0
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)