def add_post(self, request):
     form = self.form_class(request.POST, request.FILES)
     if form.is_valid():
         new_post = Post(picture=request.FILES["picture"], user=self.request.user)
         new_post.save()
         return HttpResponseRedirect(reverse("feed:index"))
     else:
         return render(request, self.template_name, {"form": form})
Exemple #2
0
    def get(self, year, month, slug):
        post = Post.get_posts_query_by_slug_within_month(slug, year, month).first()

        if not post:
            abort(404)

        return render_template(
            "posts/show.html",
            post=post,
            title=post.title,
            og_type="article",
            og_type_published=post.published_at.isoformat() or None,
            og_type_modified=post.updated_at.isoformat() or None,
            og_type_tag=",".join([tag.name for tag in post.tags])
            if post.tags
            else None,
            og_type_author=post.user.name,
        )
Exemple #3
0
    def post(self):
        preview = PreviewForm()

        return jsonify({"html": Post.convert_markdown_to_html(preview.body.data)})
Exemple #4
0
 def validate_slug(self, slug):
     if self.post_being_edited and self.post_being_edited.slug != slug.data:
         if Post.slug_exists_within_month(slug.data, self.published_at.data):
             raise ValidationError(
                 "That slug is taken for this month. Please enter a different one."
             )
Exemple #5
0
def feed(request,
         post_type=POST_TYPE_ALL,
         topic_slug=None,
         label_code=None,
         ordering=ORDERING_ACTIVITY):
    post_type = post_type or Post

    if request.me:
        request.me.update_last_activity()
        posts = Post.objects_for_user(request.me)
    else:
        posts = Post.visible_objects()

    # filter posts by type
    if post_type != POST_TYPE_ALL:
        posts = posts.filter(type=post_type)

    # filter by topic
    topic = None
    if topic_slug:
        topic = get_object_or_404(Topic, slug=topic_slug)
        posts = posts.filter(topic=topic)

    # filter by label
    if label_code:
        posts = posts.filter(label_code=label_code)

    # hide non-public posts and intros from unauthorized users
    if not request.me:
        posts = posts.exclude(is_public=False).exclude(type=Post.TYPE_INTRO)

    # exclude shadow banned posts, but show them in "new" tab
    if ordering != ORDERING_NEW:
        if request.me:
            posts = posts.exclude(
                Q(is_shadow_banned=True) & ~Q(author_id=request.me.id))
        else:
            posts = posts.exclude(is_shadow_banned=True)

    # hide no-feed posts (show only inside rooms and topics)
    if not topic and not label_code:
        posts = posts.filter(is_visible_in_feeds=True)

    # order posts by some metric
    if ordering:
        if ordering == ORDERING_ACTIVITY:
            posts = posts.order_by("-last_activity_at")
        elif ordering == ORDERING_NEW:
            posts = posts.order_by("-published_at", "-created_at")
        elif ordering == ORDERING_TOP:
            posts = posts.order_by("-upvotes")
        elif ordering == ORDERING_HOT:
            posts = posts.order_by("-hotness")
        elif ordering == ORDERING_TOP_WEEK:
            posts = posts.filter(published_at__gte=datetime.utcnow() -
                                 timedelta(days=7)).order_by("-upvotes")
        elif ordering == ORDERING_TOP_MONTH:
            posts = posts.filter(published_at__gte=datetime.utcnow() -
                                 timedelta(days=31)).order_by("-upvotes")
        else:
            raise Http404()

    # split results into pinned and unpinned posts on main page
    pinned_posts = []
    if ordering == ORDERING_ACTIVITY:
        pinned_posts = posts.filter(is_pinned_until__gte=datetime.utcnow())
        posts = posts.exclude(id__in=[p.id for p in pinned_posts])

    return render(
        request, "feed.html", {
            "post_type": post_type or POST_TYPE_ALL,
            "ordering": ordering,
            "topic": topic,
            "label_code": label_code,
            "posts": paginate(request, posts),
            "pinned_posts": pinned_posts,
            "date_month_ago": datetime.utcnow() - timedelta(days=30),
        })
Exemple #6
0
 def items(self):
     return Post.visible_objects().filter(is_public=True)
def weekly_digest(request):
    end_date = datetime.utcnow()
    start_date = end_date - timedelta(
        days=8)  # make 8, not 7, to include marginal users

    if settings.DEBUG:
        start_date = end_date - timedelta(days=1000)

    created_at_condition = dict(created_at__gte=start_date,
                                created_at__lte=end_date)
    published_at_condition = dict(published_at__gte=start_date,
                                  published_at__lte=end_date)

    # New users
    intros = Post.visible_objects()\
        .filter(type=Post.TYPE_INTRO, **published_at_condition)\
        .order_by("-upvotes")

    newbie_count = User.objects\
        .filter(
            moderation_status=User.MODERATION_STATUS_APPROVED,
            **created_at_condition
        )\
        .count()

    # Best posts
    featured_post = Post.visible_objects()\
        .exclude(type=Post.TYPE_INTRO)\
        .filter(
            label__isnull=False,
            label__code="top_week",
            **published_at_condition
         )\
        .order_by("-upvotes")\
        .first()

    posts = Post.visible_objects()\
        .filter(is_approved_by_moderator=True, **published_at_condition)\
        .exclude(type__in=[Post.TYPE_INTRO, Post.TYPE_WEEKLY_DIGEST])\
        .exclude(id=featured_post.id if featured_post else None)\
        .exclude(label__isnull=False, label__code="ad")\
        .exclude(is_shadow_banned=True)\
        .order_by("-upvotes")

    post_count = posts.count()
    posts = posts[:12]

    # Video of the week
    top_video_comment = Comment.visible_objects() \
        .filter(**created_at_condition) \
        .filter(is_deleted=False)\
        .filter(upvotes__gte=3)\
        .filter(Q(text__contains="https://youtu.be/") | Q(text__contains="youtube.com/watch"))\
        .order_by("-upvotes")\
        .first()

    top_video_post = None
    if not top_video_comment:
        top_video_post = Post.visible_objects() \
            .filter(type=Post.TYPE_LINK, upvotes__gte=3) \
            .filter(**published_at_condition) \
            .filter(Q(url__contains="https://youtu.be/") | Q(url__contains="youtube.com/watch")) \
            .order_by("-upvotes") \
            .first()

    # Best comments
    comments = Comment.visible_objects() \
        .filter(**created_at_condition) \
        .filter(is_deleted=False)\
        .exclude(post__type=Post.TYPE_BATTLE)\
        .exclude(id=top_video_comment.id if top_video_comment else None)\
        .order_by("-upvotes")[:3]

    # Intro from author
    author_intro = GodSettings.objects.first().digest_intro

    if not author_intro and not posts and not comments:
        raise Http404()

    # New achievements
    achievements = UserAchievement.objects\
        .filter(**created_at_condition)\
        .select_related("user", "achievement")\
        .order_by("achievement")  # required for grouping

    # Exclude footer for archive
    is_footer_excluded = "no_footer" in request.GET

    return render(
        request, "emails/weekly.html", {
            "posts": posts,
            "comments": comments,
            "intros": intros,
            "achievements": achievements,
            "newbie_count": newbie_count,
            "post_count": post_count,
            "top_video_comment": top_video_comment,
            "top_video_post": top_video_post,
            "featured_post": featured_post,
            "author_intro": author_intro,
            "issue_number": (end_date - settings.LAUNCH_DATE).days // 7,
            "is_footer_excluded": is_footer_excluded
        })
def daily_digest(request, user_slug):
    user = get_object_or_404(User, slug=user_slug)

    end_date = datetime.utcnow()
    start_date = end_date - timedelta(days=1)
    if end_date.weekday() == 1:
        # we don't have daily on sundays and mondays, we need to include all these posts at tuesday
        start_date = end_date - timedelta(days=3)

    if settings.DEBUG:
        start_date = end_date - timedelta(days=1000)

    created_at_condition = dict(created_at__gte=start_date,
                                created_at__lte=end_date)
    published_at_condition = dict(published_at__gte=start_date,
                                  published_at__lte=end_date)

    # Moon
    moon_phase = parse_horoscope()

    # New actions
    subscription_comments = Comment.visible_objects()\
        .filter(
            post__subscriptions__user=user,
            **created_at_condition
        )\
        .values("post__type", "post__slug", "post__title", "post__author_id")\
        .annotate(count=Count("id"))\
        .order_by()

    replies = Comment.visible_objects()\
        .filter(
            reply_to__author=user,
            **created_at_condition
        )\
        .values("post__type", "post__slug", "post__title")\
        .annotate(count=Count("reply_to_id"))\
        .order_by()

    new_events = [{
        "type":
        "my_post_comment",
        "post_url":
        reverse("show_post",
                kwargs={
                    "post_type": e["post__type"],
                    "post_slug": e["post__slug"]
                }),
        "post_title":
        e["post__title"],
        "count":
        e["count"],
    } for e in subscription_comments if e["post__author_id"] == user.id] + [{
        "type":
        "subscribed_post_comment",
        "post_url":
        reverse("show_post",
                kwargs={
                    "post_type": e["post__type"],
                    "post_slug": e["post__slug"]
                }),
        "post_title":
        e["post__title"],
        "count":
        e["count"],
    } for e in subscription_comments if e["post__author_id"] != user.id] + [{
        "type":
        "reply",
        "post_url":
        reverse("show_post",
                kwargs={
                    "post_type": e["post__type"],
                    "post_slug": e["post__slug"]
                }),
        "post_title":
        e["post__title"],
        "count":
        e["count"],
    } for e in replies]

    upvotes = PostVote.objects.filter(post__author=user, **created_at_condition).count() \
        + CommentVote.objects.filter(comment__author=user, **created_at_condition).count()

    if upvotes:
        new_events = [{
            "type": "upvotes",
            "count": upvotes,
        }] + new_events

    # Mentions
    mentions = Comment.visible_objects() \
        .filter(**created_at_condition) \
        .filter(text__regex=fr"@\y{user.slug}\y", is_deleted=False)\
        .exclude(reply_to__author=user)\
        .order_by("-upvotes")[:5]

    # Best posts
    posts = Post.visible_objects()\
        .filter(is_approved_by_moderator=True, **published_at_condition)\
        .exclude(type__in=[Post.TYPE_INTRO, Post.TYPE_WEEKLY_DIGEST])\
        .exclude(is_shadow_banned=True)\
        .order_by("-upvotes")[:100]

    # New joiners
    intros = Post.visible_objects()\
        .filter(type=Post.TYPE_INTRO, **published_at_condition)\
        .order_by("-upvotes")

    if not posts and not mentions and not intros:
        raise Http404()

    return render(
        request, "emails/daily.html", {
            "user": user,
            "events": new_events,
            "intros": intros,
            "posts": posts,
            "mentions": mentions,
            "date": end_date,
            "moon_phase": moon_phase,
        })