# retoor from devplacepy.cache import TTLCache from .core import db, get_table from .relations import get_blocked_uids PAGE_SIZE = 25 _user_post_count_cache = TTLCache(ttl=15, max_size=2000) def paginate( table, *clauses, before=None, order=None, cursor_field="created_at", viewer_uid=None, **filters, ): order = order or ["-" + cursor_field] clauses = list(clauses) if table.has_column("deleted_at") and "deleted_at" not in filters: clauses.append(table.table.columns.deleted_at.is_(None)) if viewer_uid and table.has_column("user_uid"): blocked = get_blocked_uids(viewer_uid) if blocked: clauses.append(table.table.columns.user_uid.notin_(blocked)) if before: clauses.append(table.table.columns[cursor_field] < before) rows = list(table.find(*clauses, **filters, order_by=order, _limit=PAGE_SIZE + 1)) has_more = len(rows) > PAGE_SIZE rows = rows[:PAGE_SIZE] next_cursor = rows[-1][cursor_field] if has_more and rows else None return rows, next_cursor def interleave_by_author(rows, uid_key="user_uid"): remaining = list(rows) spread = [] last_owner = object() while remaining: pick = next( ( index for index, row in enumerate(remaining) if row.get(uid_key) != last_owner ), 0, ) row = remaining.pop(pick) spread.append(row) last_owner = row.get(uid_key) return spread def paginate_diverse( table, *clauses, before=None, order=None, cursor_field="created_at", uid_key="user_uid", viewer_uid=None, **filters, ): rows, next_cursor = paginate( table, *clauses, before=before, order=order, cursor_field=cursor_field, viewer_uid=viewer_uid, **filters, ) return interleave_by_author(rows, uid_key=uid_key), next_cursor def clear_user_post_count(user_uid: str) -> None: _user_post_count_cache.pop(user_uid) def get_user_post_count(user_uid: str) -> int: cached = _user_post_count_cache.get(user_uid) if cached is not None: return cached if "posts" not in db.tables: return 0 count = get_table("posts").count(user_uid=user_uid, deleted_at=None) _user_post_count_cache.set(user_uid, count) return count def build_pagination(page, total, per_page=25): total_pages = max(1, __import__("math").ceil(total / per_page)) page = max(1, min(page, total_pages)) return { "page": page, "per_page": per_page, "total": total, "total_pages": total_pages, "has_prev": page > 1, "has_next": page < total_pages, "prev_page": page - 1, "next_page": page + 1, }