|
# retoor <retoor@molodetz.nl>
|
|
|
|
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
|