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})
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, )
def post(self): preview = PreviewForm() return jsonify({"html": Post.convert_markdown_to_html(preview.body.data)})
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." )
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), })
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, })