|
# retoor <retoor@molodetz.nl>
|
|
|
|
import logging
|
|
from datetime import datetime, timezone
|
|
|
|
from fastapi import APIRouter, Request
|
|
|
|
from devplacepy.database import (
|
|
get_table,
|
|
get_users_by_uids,
|
|
get_user_votes,
|
|
get_vote_counts,
|
|
get_user_stars,
|
|
)
|
|
from devplacepy.content import apply_vote, delete_comment_record, is_owner, is_admin
|
|
from devplacepy.services.audit import record as audit
|
|
from devplacepy.services.devrant.params import merge_params
|
|
from devplacepy.services.devrant.tokens import resolve_user
|
|
from devplacepy.services.devrant.ids import as_int, comment_by_id
|
|
from devplacepy.services.devrant.serializers import serialize_comment
|
|
from devplacepy.routers.devrant._shared import dr_ok, dr_error, unauthorized
|
|
|
|
logger = logging.getLogger(__name__)
|
|
router = APIRouter()
|
|
|
|
|
|
def _rant_id_for(comment: dict) -> int:
|
|
post = get_table("posts").find_one(uid=comment.get("target_uid"))
|
|
return int(post["id"]) if post else 0
|
|
|
|
|
|
def _serialize_single(comment: dict, viewer) -> dict:
|
|
authors = get_users_by_uids([comment["user_uid"]])
|
|
user_scores = {comment["user_uid"]: get_user_stars(comment["user_uid"])}
|
|
ups, downs = get_vote_counts([comment["uid"]])
|
|
score_map = {comment["uid"]: ups.get(comment["uid"], 0) - downs.get(comment["uid"], 0)}
|
|
my_votes = get_user_votes(viewer["uid"], [comment["uid"]]) if viewer else {}
|
|
return serialize_comment(
|
|
comment,
|
|
_rant_id_for(comment),
|
|
authors=authors,
|
|
user_scores=user_scores,
|
|
my_votes=my_votes,
|
|
score_map=score_map,
|
|
)
|
|
|
|
|
|
@router.get("/comments/{comment_id}")
|
|
async def get_comment(request: Request, comment_id: str):
|
|
params = await merge_params(request)
|
|
viewer = resolve_user(params)
|
|
comment = comment_by_id(comment_id)
|
|
if not comment:
|
|
return dr_error("Invalid comment specified in path.")
|
|
return dr_ok(comment=_serialize_single(comment, viewer))
|
|
|
|
|
|
@router.post("/comments/{comment_id}")
|
|
async def edit_comment(request: Request, comment_id: str):
|
|
params = await merge_params(request)
|
|
user = resolve_user(params)
|
|
if not user:
|
|
return unauthorized()
|
|
comment = comment_by_id(comment_id)
|
|
if not comment:
|
|
return dr_error("Invalid comment specified in path.")
|
|
if not is_owner(comment, user):
|
|
return dr_error("You can only edit your own comments.", fail_reason="not_owner")
|
|
text = (params.get("comment") or "").strip()
|
|
if len(text) < 1 or len(text) > 1000:
|
|
return dr_error("Invalid comment length.", fail_reason="length")
|
|
get_table("comments").update(
|
|
{
|
|
"uid": comment["uid"],
|
|
"content": text,
|
|
"updated_at": datetime.now(timezone.utc).isoformat(),
|
|
},
|
|
["uid"],
|
|
)
|
|
audit.record(
|
|
request,
|
|
"comment.edit",
|
|
user=user,
|
|
target_type="comment",
|
|
target_uid=comment["uid"],
|
|
origin="devrant",
|
|
summary=f"{user['username']} edited comment {comment['id']}",
|
|
links=[audit.target("comment", comment["uid"])],
|
|
)
|
|
return dr_ok()
|
|
|
|
|
|
@router.delete("/comments/{comment_id}")
|
|
async def delete_comment(request: Request, comment_id: str):
|
|
params = await merge_params(request)
|
|
user = resolve_user(params)
|
|
if not user:
|
|
return unauthorized()
|
|
comment = comment_by_id(comment_id)
|
|
if not comment:
|
|
return dr_error("Invalid comment specified in path.")
|
|
if not (is_owner(comment, user) or is_admin(user)):
|
|
return dr_error("You can only delete your own comments.")
|
|
delete_comment_record(request, user, comment)
|
|
return dr_ok()
|
|
|
|
|
|
@router.post("/comments/{comment_id}/vote")
|
|
async def vote_comment(request: Request, comment_id: str):
|
|
params = await merge_params(request)
|
|
user = resolve_user(params)
|
|
if not user:
|
|
return unauthorized()
|
|
comment = comment_by_id(comment_id)
|
|
if not comment:
|
|
return dr_error("Invalid comment specified in path.")
|
|
value = as_int(params.get("vote"))
|
|
if value not in (-1, 0, 1):
|
|
return dr_error("Invalid vote.")
|
|
apply_vote(request, user, "comment", comment["uid"], value)
|
|
return dr_ok()
|