|
# retoor <retoor@molodetz.nl>
|
|
|
|
from .core import db, get_table
|
|
from .relations import get_blocked_uids
|
|
|
|
|
|
PAGE_SIZE = 25
|
|
|
|
|
|
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 get_user_post_count(user_uid: str) -> int:
|
|
if "posts" not in db.tables:
|
|
return 0
|
|
return get_table("posts").count(user_uid=user_uid, deleted_at=None)
|
|
|
|
|
|
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,
|
|
}
|