Files
reddit-bot/backend/services/author_service.py

77 lines
2.5 KiB
Python

from datetime import datetime
from sqlalchemy import select, func
from sqlalchemy.ext.asyncio import AsyncSession
from backend.models.author import Author
from backend.models.post import Post
from backend.models.comment import Comment
async def list_authors(
db: AsyncSession,
subreddit_id: int | None = None,
sort_by: str = "total_comments",
sort_order: str = "desc",
since: datetime | None = None,
until: datetime | None = None,
page: int = 1,
per_page: int = 25,
) -> tuple[list[dict], int]:
base = select(Author)
if subreddit_id or since or until:
# Need to compute activity counts with filters
post_count = (
select(func.count(Post.id))
.where(Post.author_id == Author.id)
)
comment_count = (
select(func.count(Comment.id))
.where(Comment.author_id == Author.id)
)
if subreddit_id:
post_count = post_count.where(Post.subreddit_id == subreddit_id)
comment_count = comment_count.join(Post).where(Post.subreddit_id == subreddit_id)
if since:
post_count = post_count.where(Post.created_utc >= since)
comment_count = comment_count.where(Comment.created_utc >= since)
if until:
post_count = post_count.where(Post.created_utc <= until)
comment_count = comment_count.where(Comment.created_utc <= until)
base = select(
Author,
post_count.correlate(Author).scalar_subquery().label("filtered_posts"),
comment_count.correlate(Author).scalar_subquery().label("filtered_comments"),
)
else:
base = select(Author)
count_stmt = select(func.count()).select_from(base.subquery())
total = (await db.execute(count_stmt)).scalar() or 0
sort_col = getattr(Author, sort_by, Author.total_comments)
if sort_order == "asc":
base = base.order_by(sort_col.asc())
else:
base = base.order_by(sort_col.desc())
base = base.offset((page - 1) * per_page).limit(per_page)
result = await db.execute(base)
authors = []
for row in result.all():
author = row[0]
data = {c.name: getattr(author, c.name) for c in author.__table__.columns}
authors.append(data)
return authors, total
async def get_author(db: AsyncSession, author_id: int) -> dict | None:
author = await db.get(Author, author_id)
if not author:
return None
return {c.name: getattr(author, c.name) for c in author.__table__.columns}