# retoor from .core import _in_clause, db, defaultdict from .users import get_users_by_uids from .relations import get_blocked_uids from .engagement import get_reactions_by_targets, get_user_votes, get_vote_counts def _drop_blocked(raw, user): if not user: return raw blocked = get_blocked_uids(user["uid"]) if not blocked: return raw return [c for c in raw if c["user_uid"] not in blocked] def _build_comment_items(raw, user=None): uids = [c["user_uid"] for c in raw] cids = [c["uid"] for c in raw] users = get_users_by_uids(uids) ups, downs = get_vote_counts(cids) user_votes = get_user_votes(user["uid"], cids) if user else {} reactions = get_reactions_by_targets("comment", cids, user) from devplacepy.utils import time_ago from devplacepy.attachments import get_attachments_batch as _gab atts_map = _gab("comment", cids) if "attachments" in db.tables else {} items = {} for c in raw: items[c["uid"]] = { "comment": c, "author": users.get(c["user_uid"]), "time_ago": time_ago(c["created_at"]), "votes": {"up": ups.get(c["uid"], 0), "down": downs.get(c["uid"], 0)}, "my_vote": user_votes.get(c["uid"], 0), "children": [], "attachments": atts_map.get(c["uid"], []), "reactions": reactions.get(c["uid"], {"counts": {}, "mine": []}), } return items def load_comments(target_type, target_uid, user=None): if "comments" not in db.tables: return [] comments_table = db["comments"] raw = list( comments_table.find( target_type=target_type, target_uid=target_uid, deleted_at=None, order_by=["created_at"], ) ) if not raw and target_type == "post": raw = list( comments_table.find( post_uid=target_uid, deleted_at=None, order_by=["created_at"] ) ) raw = _drop_blocked(raw, user) if not raw: return [] cmap = _build_comment_items(raw, user) top = [] for item in cmap.values(): parent = item["comment"].get("parent_uid") if parent and parent in cmap: cmap[parent]["children"].append(item) else: top.append(item) return top def get_recent_comments_by_target_uids(target_type, target_uids, limit=3, user=None): if not target_uids or "comments" not in db.tables: return {} placeholders, params = _in_clause(target_uids) params["tt"] = target_type params["lim"] = limit raw = list( db.query( f"SELECT * FROM (" f" SELECT *, ROW_NUMBER() OVER (" f" PARTITION BY target_uid ORDER BY created_at DESC, id DESC" f" ) AS rn FROM comments" f" WHERE target_type=:tt AND target_uid IN ({placeholders}) AND deleted_at IS NULL" f") WHERE rn <= :lim ORDER BY target_uid, created_at ASC", **params, ) ) raw = _drop_blocked(raw, user) if not raw: return {} items = _build_comment_items(raw, user) by_target = defaultdict(list) for c in raw: by_target[c["target_uid"]].append(c) result = {} for target_uid, group in by_target.items(): in_group = {c["uid"] for c in group} top = [] for c in group: item = items[c["uid"]] item["children"] = [] for c in group: item = items[c["uid"]] parent = c.get("parent_uid") if parent and parent in in_group: items[parent]["children"].append(item) else: top.append(item) result[target_uid] = top return result def get_recent_comments_by_post_uids(post_uids, limit=3, user=None): return get_recent_comments_by_target_uids("post", post_uids, limit, user) def load_comments_by_target_uids(target_type, target_uids, user=None): if not target_uids or "comments" not in db.tables: return {} placeholders, params = _in_clause(target_uids) params["tt"] = target_type raw = list( db.query( f"SELECT * FROM comments WHERE target_type=:tt AND target_uid IN ({placeholders}) AND deleted_at IS NULL ORDER BY created_at", **params, ) ) raw = _drop_blocked(raw, user) if not raw: return {} from collections import defaultdict by_uid = defaultdict(list) for c in raw: by_uid[c["target_uid"]].append(c) result = {} for uid in target_uids: group = by_uid.get(uid, []) if not group: result[uid] = [] continue cmap = _build_comment_items(group, user) tree = [] for item in cmap.values(): parent = item["comment"].get("parent_uid") if parent and parent in cmap: cmap[parent]["children"].append(item) else: tree.append(item) result[uid] = tree return result