87 lines
3.7 KiB
Python
Raw Normal View History

2026-05-10 09:08:12 +02:00
import logging
from fastapi import APIRouter, Request
2026-05-11 03:14:43 +02:00
from fastapi.responses import HTMLResponse
2026-06-06 16:31:42 +02:00
from devplacepy.database import get_table, get_daily_topic, get_users_by_uids, get_comment_counts_by_post_uids, get_recent_comments_by_post_uids, get_site_stats, get_top_authors, get_reactions_by_targets, get_user_bookmarks, get_polls_by_post_uids, paginate
2026-05-12 15:07:34 +02:00
from devplacepy.attachments import get_attachments_batch
2026-05-23 08:34:13 +02:00
from devplacepy.content import enrich_items
2026-05-10 09:08:12 +02:00
from devplacepy.templating import templates
2026-05-23 08:34:13 +02:00
from devplacepy.utils import get_current_user
2026-06-05 20:05:07 +02:00
from devplacepy.seo import list_page_seo, next_page_url
2026-06-08 17:38:33 +02:00
from devplacepy.responses import respond
from devplacepy.schemas import FeedOut
2026-05-10 09:08:12 +02:00
logger = logging.getLogger(__name__)
router = APIRouter()
2026-05-11 03:14:43 +02:00
def get_feed_posts(user, tab: str = "all", topic: str = None, before: str = None):
posts_table = get_table("posts")
2026-05-29 00:45:07 +02:00
order = ["-stars", "-created_at"] if tab == "trending" else ["-created_at"]
2026-05-10 09:08:12 +02:00
if tab == "following":
2026-05-12 12:45:52 +02:00
if not user:
return [], None
2026-05-10 09:08:12 +02:00
follows = get_table("follows")
following = [f["following_uid"] for f in follows.find(follower_uid=user["uid"])]
2026-05-11 03:14:43 +02:00
if not following:
return [], None
2026-06-05 05:36:18 +02:00
posts, next_cursor = paginate(posts_table, posts_table.table.columns.user_uid.in_(following), before=before, order=order)
2026-05-11 03:14:43 +02:00
else:
2026-06-05 05:36:18 +02:00
filters = {"topic": topic} if topic else {}
posts, next_cursor = paginate(posts_table, before=before, order=order, **filters)
2026-05-10 09:08:12 +02:00
2026-05-11 03:14:43 +02:00
if not posts:
return [], next_cursor
2026-05-10 09:08:12 +02:00
2026-05-23 08:34:13 +02:00
authors = get_users_by_uids([p["user_uid"] for p in posts])
counts = get_comment_counts_by_post_uids([p["uid"] for p in posts])
2026-05-10 09:08:12 +02:00
2026-05-30 20:16:39 +02:00
result = enrich_items(posts, "post", authors, {"comment_count": counts}, user=user)
2026-05-11 03:14:43 +02:00
return result, next_cursor
2026-05-10 09:08:12 +02:00
@router.get("", response_class=HTMLResponse)
2026-05-11 03:14:43 +02:00
async def feed_page(request: Request, tab: str = "all", topic: str = None, before: str = None):
2026-05-12 12:45:52 +02:00
user = get_current_user(request)
2026-05-11 03:14:43 +02:00
posts, next_cursor = get_feed_posts(user, tab, topic, before)
2026-05-23 06:20:27 +02:00
stats = get_site_stats()
2026-05-23 10:54:45 +02:00
top_authors = get_top_authors(5)
2026-05-11 00:41:41 +02:00
daily_topic = get_daily_topic()
2026-05-10 09:08:12 +02:00
2026-05-12 15:07:34 +02:00
post_uids_list = [item["post"]["uid"] for item in posts]
attachments_map = get_attachments_batch("post", post_uids_list)
2026-06-05 18:42:43 +02:00
recent_comments = get_recent_comments_by_post_uids(post_uids_list, 3, user)
2026-06-06 16:31:42 +02:00
reactions_map = get_reactions_by_targets("post", post_uids_list, user)
bookmark_set = get_user_bookmarks(user["uid"], "post", post_uids_list) if user else set()
polls_map = get_polls_by_post_uids(post_uids_list, user)
2026-05-12 15:07:34 +02:00
for item in posts:
2026-06-05 18:42:43 +02:00
uid = item["post"]["uid"]
item["attachments"] = attachments_map.get(uid, [])
item["recent_comments"] = recent_comments.get(uid, [])
2026-06-06 16:31:42 +02:00
item["reactions"] = reactions_map.get(uid, {"counts": {}, "mine": []})
item["bookmarked"] = uid in bookmark_set
item["poll"] = polls_map.get(uid)
2026-05-12 15:07:34 +02:00
2026-05-30 20:16:39 +02:00
seo_ctx = list_page_seo(
2026-05-11 05:30:51 +02:00
request,
title="Feed",
description="Discover the latest developer discussions, projects, and community activity on DevPlace.",
breadcrumbs=[{"name": "Home", "url": "/feed"}, {"name": "Feed", "url": "/feed"}],
2026-06-05 20:05:07 +02:00
next_url=next_page_url(request, next_cursor),
2026-05-11 05:30:51 +02:00
)
2026-06-08 17:38:33 +02:00
return respond(request, "feed.html", {
2026-05-11 05:30:51 +02:00
**seo_ctx,
2026-05-10 09:08:12 +02:00
"request": request,
"user": user,
"posts": posts,
"current_tab": tab,
"current_topic": topic,
2026-05-23 06:20:27 +02:00
"total_members": stats["total_members"],
"posts_today": stats["posts_today"],
"total_projects": stats["total_projects"],
"total_gists": stats["total_gists"],
2026-05-10 09:08:12 +02:00
"top_authors": top_authors,
2026-05-11 00:41:41 +02:00
"daily_topic": daily_topic,
2026-05-11 03:14:43 +02:00
"next_cursor": next_cursor,
2026-06-08 17:38:33 +02:00
}, model=FeedOut)